diff -u -r -N squid-4.0.25/ChangeLog squid-4.1/ChangeLog
--- squid-4.0.25/ChangeLog	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/ChangeLog	2018-07-02 15:26:07.000000000 +1200
@@ -1,3 +1,10 @@
+Changes to squid-4.1 (02 Jul 2018):
+
+	- Bug 4223: fixed retries of failed re-forwardable transactions
+	- Bug 4791: Build failure on MacOS
+	- Fix --with-netfilter-conntrack error message
+	- ... and many documentation updates
+
 Changes to squid-4.0.25 (11 Jun 2018):
 
 	- Regression Bug 4855: querying private entries for HTCP/ICP
diff -u -r -N squid-4.0.25/compat/cpu.h squid-4.1/compat/cpu.h
--- squid-4.0.25/compat/cpu.h	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/compat/cpu.h	2018-07-02 15:26:07.000000000 +1200
@@ -18,7 +18,7 @@
 
 #if !HAVE_CPU_AFFINITY
 /* failing replacements to minimize the number of if-HAVE_CPU_AFFINITYs */
-#if !defined(__cpu_set_t_defined)
+#if !HAVE_CPU_SET_T
 typedef struct {
     int bits;
 } cpu_set_t;
diff -u -r -N squid-4.0.25/configure squid-4.1/configure
--- squid-4.0.25/configure	2018-06-12 04:48:04.000000000 +1200
+++ squid-4.1/configure	2018-07-02 15:32:06.000000000 +1200
@@ -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 4.0.25.
+# Generated by GNU Autoconf 2.69 for Squid Web Proxy 4.1.
 #
 # 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='4.0.25'
-PACKAGE_STRING='Squid Web Proxy 4.0.25'
+PACKAGE_VERSION='4.1'
+PACKAGE_STRING='Squid Web Proxy 4.1'
 PACKAGE_BUGREPORT='http://bugs.squid-cache.org/'
 PACKAGE_URL=''
 
@@ -1647,7 +1647,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 4.0.25 to adapt to many kinds of systems.
+\`configure' configures Squid Web Proxy 4.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1718,7 +1718,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Squid Web Proxy 4.0.25:";;
+     short | recursive ) echo "Configuration of Squid Web Proxy 4.1:";;
    esac
   cat <<\_ACEOF
 
@@ -2147,7 +2147,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Squid Web Proxy configure 4.0.25
+Squid Web Proxy configure 4.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -3251,7 +3251,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 4.0.25, which was
+It was created by Squid Web Proxy $as_me 4.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4118,7 +4118,7 @@
 
 # Define the identity of the package.
  PACKAGE='squid'
- VERSION='4.0.25'
+ VERSION='4.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -33786,7 +33786,7 @@
     ;;
   *)
     if test ! -d "$withval" ; then
-      as_fn_error $? "--without-netfilter-conntrack path does not point to a directory" "$LINENO" 5
+      as_fn_error $? "--with-netfilter-conntrack path does not point to a directory" "$LINENO" 5
     fi
     squid_opt_netfilterconntrackpath=$withval
     LDFLAGS="-L$squid_opt_netfilterconntrackpath/lib $LDFLAGS"
@@ -38732,6 +38732,19 @@
 fi
 
 
+ac_fn_cxx_check_type "$LINENO" "cpu_set_t" "ac_cv_type_cpu_set_t" "
+#if HAVE_SCHED_H
+#include <sched.h>
+#endif
+
+"
+if test "x$ac_cv_type_cpu_set_t" = xyes; then :
+
+$as_echo "#define HAVE_CPU_SET_T 1" >>confdefs.h
+
+fi
+
+
 # check for compiler support of %zu printf macro
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler %zu support" >&5
@@ -43819,7 +43832,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 4.0.25, which was
+This file was extended by Squid Web Proxy $as_me 4.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -43885,7 +43898,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 4.0.25
+Squid Web Proxy config.status 4.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -u -r -N squid-4.0.25/configure.ac squid-4.1/configure.ac
--- squid-4.0.25/configure.ac	2018-06-12 04:48:04.000000000 +1200
+++ squid-4.1/configure.ac	2018-07-02 15:32:06.000000000 +1200
@@ -5,7 +5,7 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-AC_INIT([Squid Web Proxy],[4.0.25],[http://bugs.squid-cache.org/],[squid])
+AC_INIT([Squid Web Proxy],[4.1],[http://bugs.squid-cache.org/],[squid])
 AC_PREREQ(2.61)
 AC_CONFIG_HEADERS([include/autoconf.h])
 AC_CONFIG_AUX_DIR(cfgaux)
@@ -2333,7 +2333,7 @@
     ;;
   *)
     if test ! -d "$withval" ; then
-      AC_MSG_ERROR([--without-netfilter-conntrack path does not point to a directory])
+      AC_MSG_ERROR([--with-netfilter-conntrack path does not point to a directory])
     fi
     squid_opt_netfilterconntrackpath=$withval
     LDFLAGS="-L$squid_opt_netfilterconntrackpath/lib $LDFLAGS"
@@ -3026,6 +3026,13 @@
 #include <sys/ipc.h>
 #include <sys/msg.h>])
 
+AC_CHECK_TYPE(cpu_set_t,
+   AC_DEFINE(HAVE_CPU_SET_T,1,[cpu_set_t is defined by the system headers]),,[
+#if HAVE_SCHED_H
+#include <sched.h>
+#endif
+])
+
 # check for compiler support of %zu printf macro
 AH_TEMPLATE(PRIuSIZE,[Compiler supports %zu printf macro])
 AC_MSG_CHECKING([for compiler %zu support])
diff -u -r -N squid-4.0.25/CONTRIBUTORS squid-4.1/CONTRIBUTORS
--- squid-4.0.25/CONTRIBUTORS	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/CONTRIBUTORS	2018-07-02 15:26:07.000000000 +1200
@@ -10,6 +10,8 @@
     Aleksa <susulic@gmail.com>
     Aleksa ??u??uli?? <susulic@gmail.com>
     Alexander B. Demenshin <aldem@barnet.kharkov.ua>
+    Alexander Gozman <a.gozman@securitycode.ru>
+    Alexander Gozman <goal81@gmail.com>
     Alexander Komyagin <komyagin@altell.ru>
     Alexander Lukyanov <lav@netis.ru>
     Alexander Lukyanov <lav@yar.ru>
@@ -20,15 +22,20 @@
     Alexis Robert <alexis.robert@gmail.com>
     Alex Rousskov <rousskov@measurement-factory.com>
     Alex Rousskov <rousskov@squid-cache.org>
+    Alex Wu <alex_wu2012@hotmail.com>
     Alin Nastac <mrness@gentoo.org>
     Alter <alter@alter.org.ua>
+    Amos Jeffries
     Amos Jeffries <amosjeffries@squid-cache.org>
     Amos Jeffries <squid3@treenet.co.nz>
+    Amos Jeffries <yadij@users.noreply.github.com>
     Amos <squid3@treenet.co.nz>
     Anatoli <me@anatoli.ws>
     Andrea Gagliardi <andrea@netlite.it>
+    Andre Albsmeier <Andre.Albsmeier@siemens.com>
     Andreas Jaeger <aj@suse.com>
     Andreas Lamprecht <Andreas.Lamprecht@siemens.at>
+    Andreas Weigel <andreas.weigel@securepoint.de>
     Andres Kroonmaa <andre@ml.ee>
     Andrew Balabohin
     Andrew Beverley <andy@andybev.com>
@@ -36,7 +43,9 @@
     Andrew Evdokimov <ae@elahi.ru>
     Andrew Hoying <andrew_hoying@blm.gov>
     Andrew Tridgell
+    Andrey <rybakovandrey85@gmail.com>
     Andrey Shorin <tolsty@tushino.com>
+    Anonymous <bigparrot@pirateperfection.com>
     Anonymous Pootle User
     Anonymous <redskilldough@gmail.com>
     Ansgar Hockmann <Ansgar.Hockmann@hrz.uni-dortmund.de>
@@ -52,6 +61,7 @@
     Assar Westerlund <assar@pdc.kth.se>
     Automatic source maintenance <squidadm@squid-cache.org>
     Axel Westerhold <ml.awesterhold@dts.de>
+    Aymeric Vincent <aymericvincent@free.fr>
     Barry Dobyns <barry@dobyns.com>
     Benjamin Kerensa <bkerensa@ubuntu.com>
     Benno Rice <benno@jeamland.net>
@@ -67,11 +77,13 @@
     Brian <hiryuu@envisiongames.net>
     Bruce Murphy <pack-squid@rattus.net>
     Carson Gaspar (carson@lehman.com, carson@cs.columbia.edu)
+    Carsten Grzemba <cgrzemba@opencsw.org>
     Cephas <squidwin@gmail.com>
     Chad E. Naugle <chad.naugle@travimp.com>
     Chad Naugle <chad.naugle@travimp.com>
     Changming <me@sunchangming.com>
     Chao <chao_83@126.com>
+    Chris Addie <chris.addie@datacom.com.au>
     Chris Hills <chaz@chaz6.com>
     Christian Wittmer <chris@computersalat.de>
     Christopher Kerr
@@ -79,15 +91,19 @@
     Christoph Lechleitner <lech@ibcl.at>
     Christos Tsantilas <christos@chtsanti.net>
     Christos Tsantilas <chtsanti@users.sourceforge.net>
+    Chudy Fernandez <chudy.fernandez@gmail.com>
     Cloyce <cloyce.spradling@sun.com>
     Clytie Siddall <clytie@riverland.net.au>
     Colin Coe <colin.coe@gmail.com>
     Constantin Rack
     Cord Beermann <cord@cc.fh-lippe.de>
+    Craig Gowing <craiggowing@gmail.com>
     Daniel Beschorner <daniel.beschorner@evlks.de>
     Daniel O'Callaghan <danny@miriworld.its.unimelb.EDU.AU>
     Daniel Walter <d.walter@0x90.at>
+    Dan Searle <dan@censornet.com>
     Dan Searle <dan.searle@censornet.com>
+    Dave Dykstra <dwd@fnal.gov>
     David Hill <david.hill@ubisoft.com>
     David Isaacs <david.isaacs@sbhs.nsw.edu.au>
     David J N Begley
@@ -99,23 +115,29 @@
     Dennis Glatting
     Dhaval Varia <dhavalkvaria@gmail.com>
     Diego Woitasen <diegows@xtech.com.ar>
+    Diogenes S. Jesus <splash@gmail.com>
     D Kazarov <d.y.kazarov@mail.ru>
     Dmitry Kurochkin <dmitry.kurochkin@measurement-factory.com>
     Don Hopkins <dhopkins@DonHopkins.com>
     Doug Dixon <doug.dixon@gmail.com>
     Doug Urner <dlu@bsdi.com>
     Dragutin Cirkovic <painkiller@gromnet.net>
+    DrDaveD <dwdgithub@drdykstra.us>
     drserge <drserge@inbox.ru>
     Dr. Tilmann Bubeck <t.bubeck@reinform.de>
     Duane Wessels <wessels@squid-cache.org>
     Dustin J. Mitchell
     Ed Knowles <ed@fatboy.geog.unsw.edu.au>
+    Eduard Bagdasaryan <dictiano@gmail.com>
+    Eduard Bagdasaryan <eduard.bagdasaryan@measurement-factory.com>
     Edward Chernenko <edwardspec@gmail.com>
     Edward Moy <moy@parc.xerox.com>
+    Egervary Gergely <gergely@egervary.hu>
     Eldar Akchurin <al.akchurin@googlemail.com>
     Eliezer Croitoru <eliezer@ngtech.co.il>
     Elmar Vonlanthen <Elmar.Vonlanthen@united-security-providers.ch>
     Emilio Casbas <ecasbas@unav.es>
+    Emmanuel Fuste <emmanuel.fuste@thalesgroup.com>
     Endre Balint Nagy <bne@CareNet.hu>
     Eray Aslan <eraya@a21an.org>
     Eray Aslan <eray.aslan@caf.com.tr>
@@ -144,6 +166,7 @@
     Fred <fred.maranhao@gmail.com>
     F Wolff <friedel@translate.org.za>
     Fyodor <fygrave@gmail.com>
+    Garri Djavadyan <garryd@comnet.uz>
     Geoff Keating <Geoff.Keating@anu.edu.au>
     George Michaelson <ggm@connect.com.au>
     Georgy Salnikov <sge@nmr.nioch.nsc.ru>
@@ -171,30 +194,38 @@
     Henrik Nordstrom <hno@squid-cache.org>
     Hide Nagaoka <hide@cc.meisei-u.ac.jp>
     HONDA Hirofumi <honda.hirofumi@nttcom.co.jp>
+    huaraz <huaraz@moeller.plus.com>
     Hussam Al-Tayeb <hussam@visp.net.lb>
     Ian Castle <ian.castle@coldcomfortfarm.net>
+    Ian Clark <mrrooster@gmail.com>
     Ian Turner <vectro@pipeline.com>
     Igor Vinokurov <igor@cs.ibank.ru>
     IIDA Yosiaki <y-iida@secom.co.jp>
+    Ingo Schwarze
     isaac <isaacarsenal@gmail.com>
     Isnard <isnardjaquet@gmail.com>
+    Ivan Larionov <xeron.oskom@gmail.com>
     Ivan Mas??r <helix84@centrum.sk>
     Jakob Bohm <jb-debbugs@wisemo.com>
     Jakub Wilk <jwilk@jwilk.net>
     James Bowe <minijb@gmail.com>
     James Brotchie <brotchie@gmail.com>
     James R Grinter <jrg@demon.net>
+    Jamie Strandboge
     Jan Klemkow <j.klemkow@wemelug.de>
     Jan Niehusmann <jan@anduin.gondor.mcs.de>
     Jan Sievers <sievers@zedat.fu-berlin.de>
+    Javad Kouhi <javad.kouhi@gmail.com>
     Jean-Francois Micouleau <Jean-Francois.Micouleau@utc.fr>
     Jean-Gabriel Dick <jean-gabriel.dick@curie.fr>
     Jean-Philippe Menil <jean-philippe.menil@univ-nantes.fr>
+    Jeff Licquia <jlicquia@scinet.springfieldclinic.com>
     Jens-S. V?ckler <voeckler@rvs.uni-hannover.de>
     Jeremy Allison
     Jerry Murdock <jmurdock@itraktech.com>
     Jiri Skala <jaskalnik@gmail.com>
     Jiri Skala <jskala@redhat.com>
+    jltallon
     Joachim Bauch <jojo@fistofbenztown.de>
     Joachim Bauch (mail@joachim-bauch.de)
     Joao Alves Neto <alves_joao@hotmail.com>
@@ -205,9 +236,10 @@
     Joe Ramey <ramey@jello.csc.ti.com>
     Joerg Lehrke <jlehrke@noc.de>
     Johnathan Conley <johnathan.conley@gmail.com>
+    John Dilley <jad@hpl.hp.com>
     John@MCC.ac.uk
+    John M Cooper <john.cooper@yourcommunications.co.uk>
     John@Pharmweb.NET
-    John Dilley <jad@hpl.hp.com>
     John Saunders <johns@rd.scitec.com.au>
     John Xue <xgxjohn@gmail.com>
     Jonathan Larmour <JLarmour@origin-at.co.uk>
@@ -215,6 +247,7 @@
     Jon Kinred
     Jon Thackray <jrmt@uk.gdscorp.com>
     Jorge Ivan Burgos Aguilar <jorgeivanburgosaguilar@gmail.com>
+    Jose Luis Godoy <joseluis.godoy@correo.aeat.es>
     Jose-Marcio Martins da Cruz <Jose-Marcio.Martins@mines-paristech.fr>
     Joshua Root <jmr@macports.org>
     Joshua Root <josh+squid@root.id.au>
@@ -231,8 +264,10 @@
     Lab10 <lab10@bt-anlagenbau.at>
     Laszlo Attilla Toth <panther@balabit.hu>
     Leeann Bent <lbent@cs.ucsd.edu>
+    Leonardo Taccari
     Leonid Evdokimov <leon@darkk.net.ru>
     libit <sambabug.lb@gmail.com>
+    Lubos Uhliarik <luhliari@redhat.com>
     Luigi Gangitano <luigi@debian.org>
     Luis Daniel Lucio Quiroz <dlucio@okay.com.mx>
     Lukas B??gelei <unknown>
@@ -242,6 +277,8 @@
     Marcello Romani <marcello.romani@libero.it>
     Marcin Wisnicki <mwisnicki@gmail.com>
     Marco Beck <mbeck@miamod.de>
+    Marcos Mello <marcosfrm@gmail.com>
+    Marcos Mello <marcosfrm@users.noreply.github.com>
     Marcus Kool <marcus.kool@urlfilterdb.com>
     Marc van Selm <selm@cistron.nl>
     Marin Stavrev <mstavrev@gmail.com>
@@ -252,6 +289,7 @@
     Marko <mr_4u2@yahoo.com>
     Mark Treacy <mark@aone.com.au>
     Markus Gyger <mgyger@itr.ch>
+    Markus Mayer <code@mmayer.net>
     Markus Moeller <huaraz@moeller.plus.com>
     Markus Moeller (markus_moeller at compuserve.com)
     Markus Rietzler <markus.rietzler@rzf.fin-nrw.de>
@@ -261,6 +299,7 @@
     Martin Huter <mhuter@barracuda.com>
     Martin Huter <m.huter@phion.com>
     Martin Stolle <martin.stolle@ekom21.de>
+    Martin von Gagern <martin.vgagern@gmx.net>
     Masashi Fujita <objectx@bandit.co.jp>
     Massimo Zito <zmax.linkedin at gmail dot com>
     Mathias Fischer <maf@open.ch>
@@ -270,6 +309,7 @@
     Max Okumoto <okumoto@ucsd.edu>
     Merik Karman
     <mgd@swarm.org>
+    Michael Buchau <mike@m-buchau.de>
     Michael Cunningham <m.cunningham@xpedite.com>
     Michael Lupp <mike@nemesis.saar.de>
     Michael Mansour <mic@shell.gnxs.com.au>
@@ -278,6 +318,7 @@
     Michael van Elst
     Michael Weiser <michael@weiser.dinsnail.net>
     Michal Luscon <mluscon@redhat.com>
+    Michele Bergonzoni <bergonz@labs.it>
     Miguel A.L. Paraz <map@iphil.net>
     Mike Groeneweg <mikeg@scorpion.murdoch.edu.au>
     Mike Mitchell <mike.mitchell@sas.com>
@@ -286,6 +327,7 @@
     Milen Pankov <mail@milen.pankov.eu>
     Ming Fu <mfu@watchguard.com>
     Miquel van Smoorenburg <miquels@cistron.nl>
+    mkishi <mkishi@104.net>
     Moez Mahfoudh <moez.mahfoudh@imag.fr>
     Mohsen Saeedi <mohsen.saeedi@gmail.com>
     Mukaigawa Shin'ichi <shin@nff.ncl.omron.co.jp>
@@ -303,8 +345,11 @@
     Olivier W.
     OpenSolaris Project
     Oskar Pearson <oskar@is.co.za>
+    Patrick Welche <prlw1@cam.ac.uk>
+    Paulo Matias <matias@ufscar.br>
     Paul Z <paulz42@gmail.com>
     Pavel Timofeev
+    Pavel Timofeev <timp87@gmail.com>
     Pawel Worach <pawel.worach@gmail.com>
     Pedro Lineu Orso <orso@pop.hsbcbamerindus.com.br>
     Pedro Ribeiro <pribeiro@isel.pt>
@@ -326,6 +371,7 @@
     Rafael Martinez <rmartine@fdi.ucm.es>
     Rafael Martinez Torres <rmartine@fdi.ucm.es>
     Rafal Ramocki <maniac@sistbg.net>
+    Rainer Tammer <rainer.tammer@schulergroup.com>
     Rajiv Desai <rajiv@maginatics.com>
     Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
     Ralph Loader <loader@maths.ox.ac.uk>
@@ -355,7 +401,9 @@
     R Phillips <r.phillips@uq.edu.au>
     Russell Street <r.street@auckland.ac.nz>
     Russell Vincent <vincent@ucthpx.uct.ac.za>
+    Rusty Bird <rustybird@net-c.com>
     Ryan Troll <ryan+@andrew.cmu.edu>
+    Rybakov Andrey <rybakovandrey85@gmail.com>
     Samba Project
     Santiago Garcia Mantinan <manty@debian.org>
     Scott James Remnant <scott@netsplit.com>
@@ -367,8 +415,13 @@
     Sergio Rabellino <rabellino@di.unito.it>
     Shigechika Aikawa <shige@luck.imasy.or.jp>
     Silamael <Silamael@coronamundi.de>
+    Simon Deziel
+    SquidAdm <noc@lists.squid-cache.org>
+    squidadm <squidadm@users.noreply.github.com>
     Stefan Fritsch <sf@sfritsch.de>
+    Stefan Kruger <stadtkind2@gmx.de>
     Stefano Cordibella <stefano.cordibella@edalab.it>
+    Stephen Baynes <sbaynes@mail.com>
     Stephen R. van den Berg <srb@cuci.nl>
     Stephen Thorne <stephen@thorne.id.au>
     Steve Bennett <S.Bennett@lancaster.ac.uk>
@@ -380,9 +433,12 @@
     Stuart Henderson <sthen@openbsd.org>
     Stuart Henderson <stu@spacehopper.org>
     Susant Sahani <ssahani@redhat.com>
+    Sven Eisenberg <sven.eisenberg@lairdtech.com>
     Svenx <svensven@gmail.com>
     Taavi Talvik <taavi@uninet.ee>
+    Takahiro Kambe <taca@back-street.net>
     Taketo Kabe <kabe@shiratori.riec.tohoku.ac.jp>
+    tangqinghao <tangqinghao@360.cn>
     The Measurement Factory <info@measurement-factory.com>
     The Squid Software Foundation
     Thomas De Schampheleire <thomas.de.schampheleire@gmail.com>
@@ -399,10 +455,13 @@
     Todd C. Miller <Todd.Miller@courtesan.com>
     Tomas Hozza <thozza@redhat.com>
     Tony Lorimer <tlorimer@au.mdis.com>
+    Trever Adams <trever@middleearth.sapphiresunday.org>
     Tsantilas Christos <chtsanti@users.sourceforge.net>
     Unknown
+    Unknown - Debian Project
     Unknown FreeBSD Contributor
     Unknown - NetBSD Project
+    Vadim Aleksandrov <v.verdel@gmail.com>
     Various
     Various Translators
     Victor Jose Hernandez Gomez <vjhergom@cic.upo.es>
@@ -410,11 +469,13 @@
     Vincent Regnard
     Vitaliy Matytsyn (main) <vm@if.bank.gov.ua>
     Vitaliy Matytsyn <vm@if.bank.gov.ua>
+    Vitaly Lavrov <vel21ripn@gmail.com>
     vollkommen <vollkommen@gmx.net>
     Walter <bundestrojaner2@googlemail.com>
     Wang DaQing <wdq@bigfoot.com>
     Warren Baker <warren@decoy.co.za>
     Wesha <wesha@iname.com>
+    William Lima <william.lima@hscbrasil.com.br>
     Will Roberts <squid@bigwillystyle42.com>
     Wojciech Zatorski <zator@bg.szczecin.pl>
     Wojtek Sylwestrzak <W.Sylwestrzak@icm.edu.pl>
@@ -424,4 +485,5 @@
     yabuki <yabuki@sraoss.co.jp>
     Yannick Bergeron <yaberger@ca.ibm.com>
     Yuhua Wu <ywu@bitglass.com>
+    Yuriy M. Kaminskiy <yumkam@gmail.com>
     Zhanpeng Chen <lowstz@gmail.com>
diff -u -r -N squid-4.0.25/doc/release-notes/release-4.html squid-4.1/doc/release-notes/release-4.html
--- squid-4.0.25/doc/release-notes/release-4.html	2018-06-12 04:56:17.000000000 +1200
+++ squid-4.1/doc/release-notes/release-4.html	2018-07-02 15:39:05.000000000 +1200
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.72">
- <TITLE>Squid 4.0.25 release notes</TITLE>
+ <TITLE>Squid 4.1 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 4.0.25 release notes</H1>
+<H1>Squid 4.1 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -63,13 +63,11 @@
 <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-4.0.25 for testing.</P>
+<P>The Squid Team are pleased to announce the release of Squid-4.1 for testing.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v4/">http://www.squid-cache.org/Versions/v4/</A> or the
 <A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
 
-<P>While this release is not deemed ready for production use, we believe it is ready for wider testing by the community.</P>
-
 <P>We welcome feedback and bug reports. If you find a bug, please see 
 <A HREF="http://wiki.squid-cache.org/SquidFaq/BugReporting">http://wiki.squid-cache.org/SquidFaq/BugReporting</A>
 for how to submit a report with a stack trace.</P>
@@ -77,7 +75,7 @@
 <H2><A NAME="ss1.1">1.1</A> <A HREF="#toc1.1">Known issues</A>
 </H2>
 
-<P>Although this release is deemed good enough for use in many setups, please note the existence of 
+<P>Although this release is deemed good enough for use in production, please note the existence of
 <A HREF="http://bugs.squid-cache.org/buglist.cgi?query_format=advanced&amp;product=Squid&amp;bug_status=UNCONFIRMED&amp;bug_status=NEW&amp;bug_status=ASSIGNED&amp;bug_status=REOPENED&amp;version=4">open bugs against Squid-4</A>.</P>
 
 <P>This release adds a dependency on C++11 support in any compiler used to build Squid.
@@ -165,11 +163,11 @@
 when an old TLS version is requested by the remote endpoint.</P>
 
 <P>The system Trusted CAs are no longer used by default when verifying client
-certificates. The <EM>cafile=</EM> option should be used instead to load
-the specific CA which signed acceptible client certificates explicitly,
+certificates. The <EM>cafile=</EM> option should be used instead to
+explicitly load the specific CA which signed acceptible client certificates,
 even if that CA is one of the system Trusted CAs.
 The <EM>tls-default-ca</EM> option can be used to restore the old
-behaviour explicitly if needed.</P>
+behaviour if needed.</P>
 
 
 <H2><A NAME="ss2.4">2.4</A> <A HREF="#toc2.4">Helper Binary Changes</A>
@@ -192,8 +190,9 @@
 <P>The <EM>ssl_crtd</EM> helper has been renamed to <EM>security_file_certgen</EM>
 and is now built and installed by default whenever OpenSSL support is enabled.
 Building the helper can be controlled using the <EM>--enable-security-cert-generators="file"</EM>
-option.
-NOTE: The <EM>--enable-ssl-crtd</EM> option is still required to enable the
+option.</P>
+
+<P>NOTE: The <EM>--enable-ssl-crtd</EM> option is still required to enable the
 <EM>sslcrtd_program</EM> helper interface within Squid that uses the helper.</P>
 
 <P>The <EM>ntlm_smb_lm_auth</EM> helper is now built using <EM>--enable-auth-ntlm="SMB_LM"</EM>.
@@ -219,8 +218,8 @@
 
 <P>Use of C++11 atomic operations instead of GNU atomics allows a wider range of
 operating systems and compilers to build Squid SMP and multi-process features.
-However this does require a C++11 or C++0x compiler with a recent version of
-the C++ standard library.</P>
+However this does require a C++11 compiler with a recent version of the C++
+standard library.</P>
 
 <P>IpcIo and Mmapped disk I/O modules are now auto-detected properly which
 enables Rock storage on more systems by default than previously.</P>
@@ -269,7 +268,10 @@
 
 <P>Advanced configuration with specific selection of ciphers and similar settings
 should still work, but needs the GnuTLS <EM>Priority Strings</EM> instead of
-the OpenSSL options when using GnuTLS.</P>
+the OpenSSL options when using GnuTLS.
+See 
+<A HREF="https://www.gnutls.org/manual/gnutls.html#Priority-Strings">GnuTLS manual</A>
+for more details.</P>
 
 
 <H2><A NAME="ss2.9">2.9</A> <A HREF="#toc2.9">ESI Custom Parser removal</A>
@@ -344,7 +346,7 @@
 connections. For example to HTTPS servers.</P>
 
 <DT><B>url_rewrite_timeout</B><DD>
-<P>Squid times active requests to redirector. This option sets
+<P>Squid times active requests to redirector. This directive sets
 the timeout value and the Squid reaction to a timed out
 request.</P>
 
@@ -359,7 +361,7 @@
 <DT><B>access_log</B><DD>
 <P>TCP accept(2) errors logged with URI <EM>error:accept-client-connection</EM>.</P>
 <P>Unused connections received in <EM>http_port</EM> or <EM>https_port</EM>
-or transactions terminated before reading[parsing] request headers
+or transactions terminated before reading[parsing] request headers are
 logged with URI <EM>error:transaction-end-before-headers</EM>.</P>
 <P>New option <EM>rotate=</EM> to control the number of log file rotations
 to make when <EM>-k rotate</EM> command is received. Default is to
diff -u -r -N squid-4.0.25/include/autoconf.h.in squid-4.1/include/autoconf.h.in
--- squid-4.0.25/include/autoconf.h.in	2018-06-12 04:47:56.000000000 +1200
+++ squid-4.1/include/autoconf.h.in	2018-07-02 15:32:00.000000000 +1200
@@ -137,6 +137,9 @@
 /* Support setting CPU affinity for workers */
 #undef HAVE_CPU_AFFINITY
 
+/* cpu_set_t is defined by the system headers */
+#undef HAVE_CPU_SET_T
+
 /* Define to 1 if you have the `crypt' function. */
 #undef HAVE_CRYPT
 
diff -u -r -N squid-4.0.25/include/version.h squid-4.1/include/version.h
--- squid-4.0.25/include/version.h	2018-06-12 04:48:04.000000000 +1200
+++ squid-4.1/include/version.h	2018-07-02 15:32:06.000000000 +1200
@@ -7,7 +7,7 @@
  */
 
 #ifndef SQUID_RELEASE_TIME
-#define SQUID_RELEASE_TIME 1528735673
+#define SQUID_RELEASE_TIME 1530502317
 #endif
 
 /*
diff -u -r -N squid-4.0.25/RELEASENOTES.html squid-4.1/RELEASENOTES.html
--- squid-4.0.25/RELEASENOTES.html	2018-06-12 04:56:17.000000000 +1200
+++ squid-4.1/RELEASENOTES.html	2018-07-02 15:39:05.000000000 +1200
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.72">
- <TITLE>Squid 4.0.25 release notes</TITLE>
+ <TITLE>Squid 4.1 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 4.0.25 release notes</H1>
+<H1>Squid 4.1 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -63,13 +63,11 @@
 <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-4.0.25 for testing.</P>
+<P>The Squid Team are pleased to announce the release of Squid-4.1 for testing.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v4/">http://www.squid-cache.org/Versions/v4/</A> or the
 <A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
 
-<P>While this release is not deemed ready for production use, we believe it is ready for wider testing by the community.</P>
-
 <P>We welcome feedback and bug reports. If you find a bug, please see 
 <A HREF="http://wiki.squid-cache.org/SquidFaq/BugReporting">http://wiki.squid-cache.org/SquidFaq/BugReporting</A>
 for how to submit a report with a stack trace.</P>
@@ -77,7 +75,7 @@
 <H2><A NAME="ss1.1">1.1</A> <A HREF="#toc1.1">Known issues</A>
 </H2>
 
-<P>Although this release is deemed good enough for use in many setups, please note the existence of 
+<P>Although this release is deemed good enough for use in production, please note the existence of
 <A HREF="http://bugs.squid-cache.org/buglist.cgi?query_format=advanced&amp;product=Squid&amp;bug_status=UNCONFIRMED&amp;bug_status=NEW&amp;bug_status=ASSIGNED&amp;bug_status=REOPENED&amp;version=4">open bugs against Squid-4</A>.</P>
 
 <P>This release adds a dependency on C++11 support in any compiler used to build Squid.
@@ -165,11 +163,11 @@
 when an old TLS version is requested by the remote endpoint.</P>
 
 <P>The system Trusted CAs are no longer used by default when verifying client
-certificates. The <EM>cafile=</EM> option should be used instead to load
-the specific CA which signed acceptible client certificates explicitly,
+certificates. The <EM>cafile=</EM> option should be used instead to
+explicitly load the specific CA which signed acceptible client certificates,
 even if that CA is one of the system Trusted CAs.
 The <EM>tls-default-ca</EM> option can be used to restore the old
-behaviour explicitly if needed.</P>
+behaviour if needed.</P>
 
 
 <H2><A NAME="ss2.4">2.4</A> <A HREF="#toc2.4">Helper Binary Changes</A>
@@ -192,8 +190,9 @@
 <P>The <EM>ssl_crtd</EM> helper has been renamed to <EM>security_file_certgen</EM>
 and is now built and installed by default whenever OpenSSL support is enabled.
 Building the helper can be controlled using the <EM>--enable-security-cert-generators="file"</EM>
-option.
-NOTE: The <EM>--enable-ssl-crtd</EM> option is still required to enable the
+option.</P>
+
+<P>NOTE: The <EM>--enable-ssl-crtd</EM> option is still required to enable the
 <EM>sslcrtd_program</EM> helper interface within Squid that uses the helper.</P>
 
 <P>The <EM>ntlm_smb_lm_auth</EM> helper is now built using <EM>--enable-auth-ntlm="SMB_LM"</EM>.
@@ -219,8 +218,8 @@
 
 <P>Use of C++11 atomic operations instead of GNU atomics allows a wider range of
 operating systems and compilers to build Squid SMP and multi-process features.
-However this does require a C++11 or C++0x compiler with a recent version of
-the C++ standard library.</P>
+However this does require a C++11 compiler with a recent version of the C++
+standard library.</P>
 
 <P>IpcIo and Mmapped disk I/O modules are now auto-detected properly which
 enables Rock storage on more systems by default than previously.</P>
@@ -269,7 +268,10 @@
 
 <P>Advanced configuration with specific selection of ciphers and similar settings
 should still work, but needs the GnuTLS <EM>Priority Strings</EM> instead of
-the OpenSSL options when using GnuTLS.</P>
+the OpenSSL options when using GnuTLS.
+See 
+<A HREF="https://www.gnutls.org/manual/gnutls.html#Priority-Strings">GnuTLS manual</A>
+for more details.</P>
 
 
 <H2><A NAME="ss2.9">2.9</A> <A HREF="#toc2.9">ESI Custom Parser removal</A>
@@ -344,7 +346,7 @@
 connections. For example to HTTPS servers.</P>
 
 <DT><B>url_rewrite_timeout</B><DD>
-<P>Squid times active requests to redirector. This option sets
+<P>Squid times active requests to redirector. This directive sets
 the timeout value and the Squid reaction to a timed out
 request.</P>
 
@@ -359,7 +361,7 @@
 <DT><B>access_log</B><DD>
 <P>TCP accept(2) errors logged with URI <EM>error:accept-client-connection</EM>.</P>
 <P>Unused connections received in <EM>http_port</EM> or <EM>https_port</EM>
-or transactions terminated before reading[parsing] request headers
+or transactions terminated before reading[parsing] request headers are
 logged with URI <EM>error:transaction-end-before-headers</EM>.</P>
 <P>New option <EM>rotate=</EM> to control the number of log file rotations
 to make when <EM>-k rotate</EM> command is received. Default is to
diff -u -r -N squid-4.0.25/src/acl/Asn.cc squid-4.1/src/acl/Asn.cc
--- squid-4.0.25/src/acl/Asn.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/acl/Asn.cc	2018-07-02 15:26:07.000000000 +1200
@@ -235,7 +235,7 @@
 static void
 asnCacheStart(int as)
 {
-    // TODO: use class URL instead of generating a string and re-parsing
+    // TODO: use class AnyP::Uri instead of generating a string and re-parsing
     LOCAL_ARRAY(char, asres, 4096);
     StoreEntry *e;
     ASState *asState = new ASState;
diff -u -r -N squid-4.0.25/src/acl/DomainData.cc squid-4.1/src/acl/DomainData.cc
--- squid-4.0.25/src/acl/DomainData.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/acl/DomainData.cc	2018-07-02 15:26:07.000000000 +1200
@@ -11,10 +11,10 @@
 #include "squid.h"
 #include "acl/Checklist.h"
 #include "acl/DomainData.h"
+#include "anyp/Uri.h"
 #include "cache_cf.h"
 #include "ConfigParser.h"
 #include "Debug.h"
-#include "src/URL.h"
 #include "util.h"
 
 template<class T>
diff -u -r -N squid-4.0.25/src/acl/external/delayer/ext_delayer_acl.8 squid-4.1/src/acl/external/delayer/ext_delayer_acl.8
--- squid-4.0.25/src/acl/external/delayer/ext_delayer_acl.8	2018-06-12 04:56:18.000000000 +1200
+++ squid-4.1/src/acl/external/delayer/ext_delayer_acl.8	2018-07-02 15:39:06.000000000 +1200
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_DELAYER_ACL 8"
-.TH EXT_DELAYER_ACL 8 "2018-06-11" "perl v5.26.2" "User Contributed Perl Documentation"
+.TH EXT_DELAYER_ACL 8 "2018-07-02" "perl v5.26.2" "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-4.0.25/src/acl/external/SQL_session/ext_sql_session_acl.8 squid-4.1/src/acl/external/SQL_session/ext_sql_session_acl.8
--- squid-4.0.25/src/acl/external/SQL_session/ext_sql_session_acl.8	2018-06-12 04:56:19.000000000 +1200
+++ squid-4.1/src/acl/external/SQL_session/ext_sql_session_acl.8	2018-07-02 15:39:06.000000000 +1200
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_SQL_SESSION_ACL 8"
-.TH EXT_SQL_SESSION_ACL 8 "2018-06-11" "perl v5.26.2" "User Contributed Perl Documentation"
+.TH EXT_SQL_SESSION_ACL 8 "2018-07-02" "perl v5.26.2" "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-4.0.25/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 squid-4.1/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8
--- squid-4.0.25/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8	2018-06-12 04:56:19.000000000 +1200
+++ squid-4.1/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8	2018-07-02 15:39:06.000000000 +1200
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_WBINFO_GROUP_ACL 8"
-.TH EXT_WBINFO_GROUP_ACL 8 "2018-06-11" "perl v5.26.2" "User Contributed Perl Documentation"
+.TH EXT_WBINFO_GROUP_ACL 8 "2018-07-02" "perl v5.26.2" "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-4.0.25/src/acl/ServerName.cc squid-4.1/src/acl/ServerName.cc
--- squid-4.0.25/src/acl/ServerName.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/acl/ServerName.cc	2018-07-02 15:26:07.000000000 +1200
@@ -22,7 +22,6 @@
 #include "ssl/bio.h"
 #include "ssl/ServerBump.h"
 #include "ssl/support.h"
-#include "URL.h"
 
 // Compare function for tree search algorithms
 static int
diff -u -r -N squid-4.0.25/src/acl/Url.cc squid-4.1/src/acl/Url.cc
--- squid-4.0.25/src/acl/Url.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/acl/Url.cc	2018-07-02 15:26:07.000000000 +1200
@@ -14,7 +14,6 @@
 #include "acl/Url.h"
 #include "HttpRequest.h"
 #include "rfc1738.h"
-#include "src/URL.h"
 
 int
 ACLUrlStrategy::match (ACLData<char const *> * &data, ACLFilledChecklist *checklist)
diff -u -r -N squid-4.0.25/src/adaptation/ecap/MessageRep.cc squid-4.1/src/adaptation/ecap/MessageRep.cc
--- squid-4.0.25/src/adaptation/ecap/MessageRep.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/adaptation/ecap/MessageRep.cc	2018-07-02 15:26:07.000000000 +1200
@@ -20,7 +20,6 @@
 #include "adaptation/ecap/MessageRep.h"
 #include "adaptation/ecap/XactionRep.h"
 #include "base/TextException.h"
-#include "URL.h"
 
 /* HeaderRep */
 
@@ -199,8 +198,8 @@
 void
 Adaptation::Ecap::RequestLineRep::uri(const Area &aUri)
 {
-    // TODO: if method is not set, URL::parse will assume it is not connect;
-    // Can we change URL::parse API to remove the method parameter?
+    // TODO: if method is not set, AnyP::Uri::parse will assume it is not connect;
+    // Can we change AnyP::Uri::parse API to remove the method parameter?
     const char *buf = aUri.toString().c_str();
     const bool ok = theMessage.url.parse(theMessage.method, buf);
     Must(ok);
diff -u -r -N squid-4.0.25/src/adaptation/icap/ModXact.cc squid-4.1/src/adaptation/icap/ModXact.cc
--- squid-4.0.25/src/adaptation/icap/ModXact.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/adaptation/icap/ModXact.cc	2018-07-02 15:26:07.000000000 +1200
@@ -32,7 +32,6 @@
 #include "HttpRequest.h"
 #include "MasterXaction.h"
 #include "SquidTime.h"
-#include "URL.h"
 
 // flow and terminology:
 //     HTTP| --> receive --> encode --> write --> |network
diff -u -r -N squid-4.0.25/src/adaptation/ServiceConfig.cc squid-4.1/src/adaptation/ServiceConfig.cc
--- squid-4.0.25/src/adaptation/ServiceConfig.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/adaptation/ServiceConfig.cc	2018-07-02 15:26:07.000000000 +1200
@@ -189,7 +189,7 @@
 Adaptation::ServiceConfig::grokUri(const char *value)
 {
     // TODO: find core code that parses URLs and extracts various parts
-    // AYJ: most of this is duplicate of URL::parse() in src/url.cc
+    // AYJ: most of this is duplicate of AnyP::Uri::parse()
 
     if (!value || !*value) {
         debugs(3, DBG_CRITICAL, HERE << cfg_filename << ':' << config_lineno << ": " <<
diff -u -r -N squid-4.0.25/src/anyp/forward.h squid-4.1/src/anyp/forward.h
--- squid-4.0.25/src/anyp/forward.h	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/anyp/forward.h	2018-07-02 15:26:07.000000000 +1200
@@ -17,6 +17,7 @@
 class PortCfg;
 typedef RefCount<PortCfg> PortCfgPointer;
 
+class Uri;
 class UriScheme;
 
 } // namespace AnyP
diff -u -r -N squid-4.0.25/src/anyp/Makefile.am squid-4.1/src/anyp/Makefile.am
--- squid-4.0.25/src/anyp/Makefile.am	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/anyp/Makefile.am	2018-07-02 15:26:07.000000000 +1200
@@ -18,6 +18,8 @@
 	ProtocolType.h \
 	ProtocolVersion.h \
 	TrafficMode.h \
+	Uri.cc \
+	Uri.h \
 	UriScheme.cc \
 	UriScheme.h
 
diff -u -r -N squid-4.0.25/src/anyp/Makefile.in squid-4.1/src/anyp/Makefile.in
--- squid-4.0.25/src/anyp/Makefile.in	2018-06-12 04:48:00.000000000 +1200
+++ squid-4.1/src/anyp/Makefile.in	2018-07-02 15:32:03.000000000 +1200
@@ -163,7 +163,7 @@
 CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 libanyp_la_LIBADD =
-am_libanyp_la_OBJECTS = PortCfg.lo ProtocolType.lo UriScheme.lo
+am_libanyp_la_OBJECTS = PortCfg.lo ProtocolType.lo Uri.lo UriScheme.lo
 libanyp_la_OBJECTS = $(am_libanyp_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -724,6 +724,8 @@
 	ProtocolType.h \
 	ProtocolVersion.h \
 	TrafficMode.h \
+	Uri.cc \
+	Uri.h \
 	UriScheme.cc \
 	UriScheme.h
 
@@ -793,6 +795,7 @@
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PortCfg.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ProtocolType.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Uri.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriScheme.Plo@am__quote@
 
 .cc.o:
diff -u -r -N squid-4.0.25/src/anyp/Uri.cc squid-4.1/src/anyp/Uri.cc
--- squid-4.0.25/src/anyp/Uri.cc	1970-01-01 12:00:00.000000000 +1200
+++ squid-4.1/src/anyp/Uri.cc	2018-07-02 15:26:07.000000000 +1200
@@ -0,0 +1,938 @@
+/*
+ * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 23    URL Parsing */
+
+#include "squid.h"
+#include "anyp/Uri.h"
+#include "globals.h"
+#include "HttpRequest.h"
+#include "rfc1738.h"
+#include "SquidConfig.h"
+#include "SquidString.h"
+
+static const char valid_hostname_chars_u[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyz"
+    "0123456789-._"
+    "[:]"
+    ;
+static const char valid_hostname_chars[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyz"
+    "0123456789-."
+    "[:]"
+    ;
+
+const SBuf &
+AnyP::Uri::Asterisk()
+{
+    static SBuf star("*");
+    return star;
+}
+
+const SBuf &
+AnyP::Uri::SlashPath()
+{
+    static SBuf slash("/");
+    return slash;
+}
+
+void
+AnyP::Uri::host(const char *src)
+{
+    hostAddr_.setEmpty();
+    hostAddr_ = src;
+    if (hostAddr_.isAnyAddr()) {
+        xstrncpy(host_, src, sizeof(host_));
+        hostIsNumeric_ = false;
+    } else {
+        hostAddr_.toHostStr(host_, sizeof(host_));
+        debugs(23, 3, "given IP: " << hostAddr_);
+        hostIsNumeric_ = 1;
+    }
+    touch();
+}
+
+const SBuf &
+AnyP::Uri::path() const
+{
+    // RFC 3986 section 3.3 says path can be empty (path-abempty).
+    // RFC 7230 sections 2.7.3, 5.3.1, 5.7.2 - says path cannot be empty, default to "/"
+    // at least when sending and using. We must still accept path-abempty as input.
+    if (path_.isEmpty() && (scheme_ == AnyP::PROTO_HTTP || scheme_ == AnyP::PROTO_HTTPS))
+        return SlashPath();
+
+    return path_;
+}
+
+void
+urlInitialize(void)
+{
+    debugs(23, 5, "urlInitialize: Initializing...");
+    /* this ensures that the number of protocol strings is the same as
+     * the enum slots allocated because the last enum is always 'MAX'.
+     */
+    assert(strcmp(AnyP::ProtocolType_str[AnyP::PROTO_MAX], "MAX") == 0);
+    /*
+     * These test that our matchDomainName() function works the
+     * way we expect it to.
+     */
+    assert(0 == matchDomainName("foo.com", "foo.com"));
+    assert(0 == matchDomainName(".foo.com", "foo.com"));
+    assert(0 == matchDomainName("foo.com", ".foo.com"));
+    assert(0 == matchDomainName(".foo.com", ".foo.com"));
+    assert(0 == matchDomainName("x.foo.com", ".foo.com"));
+    assert(0 == matchDomainName("y.x.foo.com", ".foo.com"));
+    assert(0 != matchDomainName("x.foo.com", "foo.com"));
+    assert(0 != matchDomainName("foo.com", "x.foo.com"));
+    assert(0 != matchDomainName("bar.com", "foo.com"));
+    assert(0 != matchDomainName(".bar.com", "foo.com"));
+    assert(0 != matchDomainName(".bar.com", ".foo.com"));
+    assert(0 != matchDomainName("bar.com", ".foo.com"));
+    assert(0 < matchDomainName("zzz.com", "foo.com"));
+    assert(0 > matchDomainName("aaa.com", "foo.com"));
+    assert(0 == matchDomainName("FOO.com", "foo.COM"));
+    assert(0 < matchDomainName("bfoo.com", "afoo.com"));
+    assert(0 > matchDomainName("afoo.com", "bfoo.com"));
+    assert(0 < matchDomainName("x-foo.com", ".foo.com"));
+
+    assert(0 == matchDomainName(".foo.com", ".foo.com", mdnRejectSubsubDomains));
+    assert(0 == matchDomainName("x.foo.com", ".foo.com", mdnRejectSubsubDomains));
+    assert(0 != matchDomainName("y.x.foo.com", ".foo.com", mdnRejectSubsubDomains));
+    assert(0 != matchDomainName(".x.foo.com", ".foo.com", mdnRejectSubsubDomains));
+
+    assert(0 == matchDomainName("*.foo.com", "x.foo.com", mdnHonorWildcards));
+    assert(0 == matchDomainName("*.foo.com", ".x.foo.com", mdnHonorWildcards));
+    assert(0 == matchDomainName("*.foo.com", ".foo.com", mdnHonorWildcards));
+    assert(0 != matchDomainName("*.foo.com", "foo.com", mdnHonorWildcards));
+
+    /* more cases? */
+}
+
+/**
+ * Parse the scheme name from string b, into protocol type.
+ * The string must be 0-terminated.
+ */
+AnyP::ProtocolType
+urlParseProtocol(const char *b)
+{
+    // make e point to the ':' character
+    const char *e = b + strcspn(b, ":");
+    int len = e - b;
+
+    /* test common stuff first */
+
+    if (strncasecmp(b, "http", len) == 0)
+        return AnyP::PROTO_HTTP;
+
+    if (strncasecmp(b, "ftp", len) == 0)
+        return AnyP::PROTO_FTP;
+
+    if (strncasecmp(b, "https", len) == 0)
+        return AnyP::PROTO_HTTPS;
+
+    if (strncasecmp(b, "file", len) == 0)
+        return AnyP::PROTO_FTP;
+
+    if (strncasecmp(b, "coap", len) == 0)
+        return AnyP::PROTO_COAP;
+
+    if (strncasecmp(b, "coaps", len) == 0)
+        return AnyP::PROTO_COAPS;
+
+    if (strncasecmp(b, "gopher", len) == 0)
+        return AnyP::PROTO_GOPHER;
+
+    if (strncasecmp(b, "wais", len) == 0)
+        return AnyP::PROTO_WAIS;
+
+    if (strncasecmp(b, "cache_object", len) == 0)
+        return AnyP::PROTO_CACHE_OBJECT;
+
+    if (strncasecmp(b, "urn", len) == 0)
+        return AnyP::PROTO_URN;
+
+    if (strncasecmp(b, "whois", len) == 0)
+        return AnyP::PROTO_WHOIS;
+
+    if (len > 0)
+        return AnyP::PROTO_UNKNOWN;
+
+    return AnyP::PROTO_NONE;
+}
+
+/*
+ * Parse a URI/URL.
+ *
+ * Stores parsed values in the `request` argument.
+ *
+ * This abuses HttpRequest as a way of representing the parsed url
+ * and its components.
+ * method is used to switch parsers and to init the HttpRequest.
+ * If method is Http::METHOD_CONNECT, then rather than a URL a hostname:port is
+ * looked for.
+ * The url is non const so that if its too long we can NULL-terminate it in place.
+ */
+
+/*
+ * This routine parses a URL. Its assumed that the URL is complete -
+ * ie, the end of the string is the end of the URL. Don't pass a partial
+ * URL here as this routine doesn't have any way of knowing whether
+ * its partial or not (ie, it handles the case of no trailing slash as
+ * being "end of host with implied path of /".
+ */
+bool
+AnyP::Uri::parse(const HttpRequestMethod& method, const char *url)
+{
+    LOCAL_ARRAY(char, proto, MAX_URL);
+    LOCAL_ARRAY(char, login, MAX_URL);
+    LOCAL_ARRAY(char, foundHost, MAX_URL);
+    LOCAL_ARRAY(char, urlpath, MAX_URL);
+    char *t = NULL;
+    char *q = NULL;
+    int foundPort;
+    AnyP::ProtocolType protocol = AnyP::PROTO_NONE;
+    int l;
+    int i;
+    const char *src;
+    char *dst;
+    proto[0] = foundHost[0] = urlpath[0] = login[0] = '\0';
+
+    if ((l = strlen(url)) + Config.appendDomainLen > (MAX_URL - 1)) {
+        debugs(23, DBG_IMPORTANT, MYNAME << "URL too large (" << l << " bytes)");
+        return false;
+    }
+    if (method == Http::METHOD_CONNECT) {
+        /*
+         * RFC 7230 section 5.3.3:  authority-form = authority
+         *  "excluding any userinfo and its "@" delimiter"
+         *
+         * RFC 3986 section 3.2:    authority = [ userinfo "@" ] host [ ":" port ]
+         *
+         * As an HTTP(S) proxy we assume HTTPS (443) if no port provided.
+         */
+        foundPort = 443;
+
+        if (sscanf(url, "[%[^]]]:%d", foundHost, &foundPort) < 1)
+            if (sscanf(url, "%[^:]:%d", foundHost, &foundPort) < 1)
+                return false;
+
+    } else if ((method == Http::METHOD_OPTIONS || method == Http::METHOD_TRACE) &&
+               AnyP::Uri::Asterisk().cmp(url) == 0) {
+        parseFinish(AnyP::PROTO_HTTP, nullptr, url, foundHost, SBuf(), 80 /* HTTP default port */);
+        return true;
+    } else if (strncmp(url, "urn:", 4) == 0) {
+        debugs(23, 3, "Split URI '" << url << "' into proto='urn', path='" << (url+4) << "'");
+        debugs(50, 5, "urn=" << (url+4));
+        setScheme(AnyP::PROTO_URN, nullptr);
+        path(url + 4);
+        return true;
+    } else {
+        /* Parse the URL: */
+        src = url;
+        i = 0;
+        /* Find first : - everything before is protocol */
+        for (i = 0, dst = proto; i < l && *src != ':'; ++i, ++src, ++dst) {
+            *dst = *src;
+        }
+        if (i >= l)
+            return false;
+        *dst = '\0';
+
+        /* Then its :// */
+        if ((i+3) > l || *src != ':' || *(src + 1) != '/' || *(src + 2) != '/')
+            return false;
+        i += 3;
+        src += 3;
+
+        /* Then everything until first /; thats host (and port; which we'll look for here later) */
+        // bug 1881: If we don't get a "/" then we imply it was there
+        // bug 3074: We could just be given a "?" or "#". These also imply "/"
+        // bug 3233: whitespace is also a hostname delimiter.
+        for (dst = foundHost; i < l && *src != '/' && *src != '?' && *src != '#' && *src != '\0' && !xisspace(*src); ++i, ++src, ++dst) {
+            *dst = *src;
+        }
+
+        /*
+         * We can't check for "i >= l" here because we could be at the end of the line
+         * and have a perfectly valid URL w/ no trailing '/'. In this case we assume we've
+         * been -given- a valid URL and the path is just '/'.
+         */
+        if (i > l)
+            return false;
+        *dst = '\0';
+
+        // bug 3074: received 'path' starting with '?', '#', or '\0' implies '/'
+        if (*src == '?' || *src == '#' || *src == '\0') {
+            urlpath[0] = '/';
+            dst = &urlpath[1];
+        } else {
+            dst = urlpath;
+        }
+        /* Then everything from / (inclusive) until \r\n or \0 - thats urlpath */
+        for (; i < l && *src != '\r' && *src != '\n' && *src != '\0'; ++i, ++src, ++dst) {
+            *dst = *src;
+        }
+
+        /* We -could- be at the end of the buffer here */
+        if (i > l)
+            return false;
+        /* If the URL path is empty we set it to be "/" */
+        if (dst == urlpath) {
+            *dst = '/';
+            ++dst;
+        }
+        *dst = '\0';
+
+        protocol = urlParseProtocol(proto);
+        foundPort = AnyP::UriScheme(protocol).defaultPort();
+
+        /* Is there any login information? (we should eventually parse it above) */
+        t = strrchr(foundHost, '@');
+        if (t != NULL) {
+            strncpy((char *) login, (char *) foundHost, sizeof(login)-1);
+            login[sizeof(login)-1] = '\0';
+            t = strrchr(login, '@');
+            *t = 0;
+            strncpy((char *) foundHost, t + 1, sizeof(foundHost)-1);
+            foundHost[sizeof(foundHost)-1] = '\0';
+            // Bug 4498: URL-unescape the login info after extraction
+            rfc1738_unescape(login);
+        }
+
+        /* Is there any host information? (we should eventually parse it above) */
+        if (*foundHost == '[') {
+            /* strip any IPA brackets. valid under IPv6. */
+            dst = foundHost;
+            /* only for IPv6 sadly, pre-IPv6/URL code can't handle the clean result properly anyway. */
+            src = foundHost;
+            ++src;
+            l = strlen(foundHost);
+            i = 1;
+            for (; i < l && *src != ']' && *src != '\0'; ++i, ++src, ++dst) {
+                *dst = *src;
+            }
+
+            /* we moved in-place, so truncate the actual hostname found */
+            *dst = '\0';
+            ++dst;
+
+            /* skip ahead to either start of port, or original EOS */
+            while (*dst != '\0' && *dst != ':')
+                ++dst;
+            t = dst;
+        } else {
+            t = strrchr(foundHost, ':');
+
+            if (t != strchr(foundHost,':') ) {
+                /* RFC 2732 states IPv6 "SHOULD" be bracketed. allowing for times when its not. */
+                /* RFC 3986 'update' simply modifies this to an "is" with no emphasis at all! */
+                /* therefore we MUST accept the case where they are not bracketed at all. */
+                t = NULL;
+            }
+        }
+
+        // Bug 3183 sanity check: If scheme is present, host must be too.
+        if (protocol != AnyP::PROTO_NONE && foundHost[0] == '\0') {
+            debugs(23, DBG_IMPORTANT, "SECURITY ALERT: Missing hostname in URL '" << url << "'. see access.log for details.");
+            return false;
+        }
+
+        if (t && *t == ':') {
+            *t = '\0';
+            ++t;
+            foundPort = atoi(t);
+        }
+    }
+
+    for (t = foundHost; *t; ++t)
+        *t = xtolower(*t);
+
+    if (stringHasWhitespace(foundHost)) {
+        if (URI_WHITESPACE_STRIP == Config.uri_whitespace) {
+            t = q = foundHost;
+            while (*t) {
+                if (!xisspace(*t)) {
+                    *q = *t;
+                    ++q;
+                }
+                ++t;
+            }
+            *q = '\0';
+        }
+    }
+
+    debugs(23, 3, "Split URL '" << url << "' into proto='" << proto << "', host='" << foundHost << "', port='" << foundPort << "', path='" << urlpath << "'");
+
+    if (Config.onoff.check_hostnames &&
+            strspn(foundHost, Config.onoff.allow_underscore ? valid_hostname_chars_u : valid_hostname_chars) != strlen(foundHost)) {
+        debugs(23, DBG_IMPORTANT, MYNAME << "Illegal character in hostname '" << foundHost << "'");
+        return false;
+    }
+
+    /* For IPV6 addresses also check for a colon */
+    if (Config.appendDomain && !strchr(foundHost, '.') && !strchr(foundHost, ':'))
+        strncat(foundHost, Config.appendDomain, SQUIDHOSTNAMELEN - strlen(foundHost) - 1);
+
+    /* remove trailing dots from hostnames */
+    while ((l = strlen(foundHost)) > 0 && foundHost[--l] == '.')
+        foundHost[l] = '\0';
+
+    /* reject duplicate or leading dots */
+    if (strstr(foundHost, "..") || *foundHost == '.') {
+        debugs(23, DBG_IMPORTANT, MYNAME << "Illegal hostname '" << foundHost << "'");
+        return false;
+    }
+
+    if (foundPort < 1 || foundPort > 65535) {
+        debugs(23, 3, "Invalid port '" << foundPort << "'");
+        return false;
+    }
+
+#if HARDCODE_DENY_PORTS
+    /* These ports are filtered in the default squid.conf, but
+     * maybe someone wants them hardcoded... */
+    if (foundPort == 7 || foundPort == 9 || foundPort == 19) {
+        debugs(23, DBG_CRITICAL, MYNAME << "Deny access to port " << foundPort);
+        return false;
+    }
+#endif
+
+    if (stringHasWhitespace(urlpath)) {
+        debugs(23, 2, "URI has whitespace: {" << url << "}");
+
+        switch (Config.uri_whitespace) {
+
+        case URI_WHITESPACE_DENY:
+            return false;
+
+        case URI_WHITESPACE_ALLOW:
+            break;
+
+        case URI_WHITESPACE_ENCODE:
+            t = rfc1738_escape_unescaped(urlpath);
+            xstrncpy(urlpath, t, MAX_URL);
+            break;
+
+        case URI_WHITESPACE_CHOP:
+            *(urlpath + strcspn(urlpath, w_space)) = '\0';
+            break;
+
+        case URI_WHITESPACE_STRIP:
+        default:
+            t = q = urlpath;
+            while (*t) {
+                if (!xisspace(*t)) {
+                    *q = *t;
+                    ++q;
+                }
+                ++t;
+            }
+            *q = '\0';
+        }
+    }
+
+    parseFinish(protocol, proto, urlpath, foundHost, SBuf(login), foundPort);
+    return true;
+}
+
+/// Update the URL object with parsed URI data.
+void
+AnyP::Uri::parseFinish(const AnyP::ProtocolType protocol,
+                 const char *const protoStr, // for unknown protocols
+                 const char *const aUrlPath,
+                 const char *const aHost,
+                 const SBuf &aLogin,
+                 const int aPort)
+{
+    setScheme(protocol, protoStr);
+    path(aUrlPath);
+    host(aHost);
+    userInfo(aLogin);
+    port(aPort);
+}
+
+void
+AnyP::Uri::touch()
+{
+    absolute_.clear();
+    authorityHttp_.clear();
+    authorityWithPort_.clear();
+}
+
+SBuf &
+AnyP::Uri::authority(bool requirePort) const
+{
+    if (authorityHttp_.isEmpty()) {
+
+        // both formats contain Host/IP
+        authorityWithPort_.append(host());
+        authorityHttp_ = authorityWithPort_;
+
+        // authorityForm_ only has :port if it is non-default
+        authorityWithPort_.appendf(":%u",port());
+        if (port() != getScheme().defaultPort())
+            authorityHttp_ = authorityWithPort_;
+    }
+
+    return requirePort ? authorityWithPort_ : authorityHttp_;
+}
+
+SBuf &
+AnyP::Uri::absolute() const
+{
+    if (absolute_.isEmpty()) {
+        // TODO: most URL will be much shorter, avoid allocating this much
+        absolute_.reserveCapacity(MAX_URL);
+
+        absolute_.append(getScheme().image());
+        absolute_.append(":",1);
+        if (getScheme() != AnyP::PROTO_URN) {
+            absolute_.append("//", 2);
+            const bool omitUserInfo = getScheme() == AnyP::PROTO_HTTP ||
+                                      getScheme() != AnyP::PROTO_HTTPS ||
+                                      userInfo().isEmpty();
+            if (!omitUserInfo) {
+                absolute_.append(userInfo());
+                absolute_.append("@", 1);
+            }
+            absolute_.append(authority());
+        }
+        absolute_.append(path());
+    }
+
+    return absolute_;
+}
+
+/** \todo AYJ: Performance: This is an *almost* duplicate of HttpRequest::effectiveRequestUri(). But elides the query-string.
+ *        After copying it on in the first place! Would be less code to merge the two with a flag parameter.
+ *        and never copy the query-string part in the first place
+ */
+char *
+urlCanonicalClean(const HttpRequest * request)
+{
+    LOCAL_ARRAY(char, buf, MAX_URL);
+
+    snprintf(buf, sizeof(buf), SQUIDSBUFPH, SQUIDSBUFPRINT(request->effectiveRequestUri()));
+    buf[sizeof(buf)-1] = '\0';
+
+    // URN, CONNECT method, and non-stripped URIs can go straight out
+    if (Config.onoff.strip_query_terms && !(request->method == Http::METHOD_CONNECT || request->url.getScheme() == AnyP::PROTO_URN)) {
+        // strip anything AFTER a question-mark
+        // leaving the '?' in place
+        if (auto t = strchr(buf, '?')) {
+            *(++t) = '\0';
+        }
+    }
+
+    if (stringHasCntl(buf))
+        xstrncpy(buf, rfc1738_escape_unescaped(buf), MAX_URL);
+
+    return buf;
+}
+
+/**
+ * Yet another alternative to urlCanonical.
+ * This one adds the https:// parts to Http::METHOD_CONNECT URL
+ * for use in error page outputs.
+ * Luckily we can leverage the others instead of duplicating.
+ */
+const char *
+urlCanonicalFakeHttps(const HttpRequest * request)
+{
+    LOCAL_ARRAY(char, buf, MAX_URL);
+
+    // method CONNECT and port HTTPS
+    if (request->method == Http::METHOD_CONNECT && request->url.port() == 443) {
+        snprintf(buf, MAX_URL, "https://%s/*", request->url.host());
+        return buf;
+    }
+
+    // else do the normal complete canonical thing.
+    return urlCanonicalClean(request);
+}
+
+/*
+ * Test if a URL is relative.
+ *
+ * RFC 2396, Section 5 (Page 17) implies that in a relative URL, a '/' will
+ * appear before a ':'.
+ */
+bool
+urlIsRelative(const char *url)
+{
+    const char *p;
+
+    if (url == NULL) {
+        return (false);
+    }
+    if (*url == '\0') {
+        return (false);
+    }
+
+    for (p = url; *p != '\0' && *p != ':' && *p != '/'; ++p);
+
+    if (*p == ':') {
+        return (false);
+    }
+    return (true);
+}
+
+/*
+ * Convert a relative URL to an absolute URL using the context of a given
+ * request.
+ *
+ * It is assumed that you have already ensured that the URL is relative.
+ *
+ * If NULL is returned it is an indication that the method in use in the
+ * request does not distinguish between relative and absolute and you should
+ * use the url unchanged.
+ *
+ * If non-NULL is returned, it is up to the caller to free the resulting
+ * memory using safe_free().
+ */
+char *
+urlMakeAbsolute(const HttpRequest * req, const char *relUrl)
+{
+
+    if (req->method.id() == Http::METHOD_CONNECT) {
+        return (NULL);
+    }
+
+    char *urlbuf = (char *)xmalloc(MAX_URL * sizeof(char));
+
+    if (req->url.getScheme() == AnyP::PROTO_URN) {
+        // XXX: this is what the original code did, but it seems to break the
+        // intended behaviour of this function. It returns the stored URN path,
+        // not converting the given one into a URN...
+        snprintf(urlbuf, MAX_URL, SQUIDSBUFPH, SQUIDSBUFPRINT(req->url.absolute()));
+        return (urlbuf);
+    }
+
+    SBuf authorityForm = req->url.authority(); // host[:port]
+    const SBuf &scheme = req->url.getScheme().image();
+    size_t urllen = snprintf(urlbuf, MAX_URL, SQUIDSBUFPH "://" SQUIDSBUFPH "%s" SQUIDSBUFPH,
+                             SQUIDSBUFPRINT(scheme),
+                             SQUIDSBUFPRINT(req->url.userInfo()),
+                             !req->url.userInfo().isEmpty() ? "@" : "",
+                             SQUIDSBUFPRINT(authorityForm));
+
+    // if the first char is '/' assume its a relative path
+    // XXX: this breaks on scheme-relative URLs,
+    // but we should not see those outside ESI, and rarely there.
+    // XXX: also breaks on any URL containing a '/' in the query-string portion
+    if (relUrl[0] == '/') {
+        xstrncpy(&urlbuf[urllen], relUrl, MAX_URL - urllen - 1);
+    } else {
+        SBuf path = req->url.path();
+        SBuf::size_type lastSlashPos = path.rfind('/');
+
+        if (lastSlashPos == SBuf::npos) {
+            // replace the whole path with the given bit(s)
+            urlbuf[urllen] = '/';
+            ++urllen;
+            xstrncpy(&urlbuf[urllen], relUrl, MAX_URL - urllen - 1);
+        } else {
+            // replace only the last (file?) segment with the given bit(s)
+            ++lastSlashPos;
+            if (lastSlashPos > MAX_URL - urllen - 1) {
+                // XXX: crops bits in the middle of the combined URL.
+                lastSlashPos = MAX_URL - urllen - 1;
+            }
+            SBufToCstring(&urlbuf[urllen], path.substr(0,lastSlashPos));
+            urllen += lastSlashPos;
+            if (urllen + 1 < MAX_URL) {
+                xstrncpy(&urlbuf[urllen], relUrl, MAX_URL - urllen - 1);
+            }
+        }
+    }
+
+    return (urlbuf);
+}
+
+int
+matchDomainName(const char *h, const char *d, uint flags)
+{
+    int dl;
+    int hl;
+
+    const bool hostIncludesSubdomains = (*h == '.');
+    while ('.' == *h)
+        ++h;
+
+    hl = strlen(h);
+
+    if (hl == 0)
+        return -1;
+
+    dl = strlen(d);
+
+    /*
+     * Start at the ends of the two strings and work towards the
+     * beginning.
+     */
+    while (xtolower(h[--hl]) == xtolower(d[--dl])) {
+        if (hl == 0 && dl == 0) {
+            /*
+             * We made it all the way to the beginning of both
+             * strings without finding any difference.
+             */
+            return 0;
+        }
+
+        if (0 == hl) {
+            /*
+             * The host string is shorter than the domain string.
+             * There is only one case when this can be a match.
+             * If the domain is just one character longer, and if
+             * that character is a leading '.' then we call it a
+             * match.
+             */
+
+            if (1 == dl && '.' == d[0])
+                return 0;
+            else
+                return -1;
+        }
+
+        if (0 == dl) {
+            /*
+             * The domain string is shorter than the host string.
+             * This is a match only if the first domain character
+             * is a leading '.'.
+             */
+
+            if ('.' == d[0]) {
+                if (flags & mdnRejectSubsubDomains) {
+                    // Check for sub-sub domain and reject
+                    while(--hl >= 0 && h[hl] != '.');
+                    if (hl < 0) {
+                        // No sub-sub domain found, but reject if there is a
+                        // leading dot in given host string (which is removed
+                        // before the check is started).
+                        return hostIncludesSubdomains ? 1 : 0;
+                    } else
+                        return 1; // sub-sub domain, reject
+                } else
+                    return 0;
+            } else
+                return 1;
+        }
+    }
+
+    /*
+     * We found different characters in the same position (from the end).
+     */
+
+    // If the h has a form of "*.foo.com" and d has a form of "x.foo.com"
+    // then the h[hl] points to '*', h[hl+1] to '.' and d[dl] to 'x'
+    // The following checks are safe, the "h[hl + 1]" in the worst case is '\0'.
+    if ((flags & mdnHonorWildcards) && h[hl] == '*' && h[hl + 1] == '.')
+        return 0;
+
+    /*
+     * If one of those character is '.' then its special.  In order
+     * for splay tree sorting to work properly, "x-foo.com" must
+     * be greater than ".foo.com" even though '-' is less than '.'.
+     */
+    if ('.' == d[dl])
+        return 1;
+
+    if ('.' == h[hl])
+        return -1;
+
+    return (xtolower(h[hl]) - xtolower(d[dl]));
+}
+
+/*
+ * return true if we can serve requests for this method.
+ */
+int
+urlCheckRequest(const HttpRequest * r)
+{
+    int rc = 0;
+    /* protocol "independent" methods
+     *
+     * actually these methods are specific to HTTP:
+     * they are methods we recieve on our HTTP port,
+     * and if we had a FTP listener would not be relevant
+     * there.
+     *
+     * So, we should delegate them to HTTP. The problem is that we
+     * do not have a default protocol from the client side of HTTP.
+     */
+
+    if (r->method == Http::METHOD_CONNECT)
+        return 1;
+
+    // we support OPTIONS and TRACE directed at us (with a 501 reply, for now)
+    // we also support forwarding OPTIONS and TRACE, except for the *-URI ones
+    if (r->method == Http::METHOD_OPTIONS || r->method == Http::METHOD_TRACE)
+        return (r->header.getInt64(Http::HdrType::MAX_FORWARDS) == 0 || r->url.path() != AnyP::Uri::Asterisk());
+
+    if (r->method == Http::METHOD_PURGE)
+        return 1;
+
+    /* does method match the protocol? */
+    switch (r->url.getScheme()) {
+
+    case AnyP::PROTO_URN:
+
+    case AnyP::PROTO_HTTP:
+
+    case AnyP::PROTO_CACHE_OBJECT:
+        rc = 1;
+        break;
+
+    case AnyP::PROTO_FTP:
+
+        if (r->method == Http::METHOD_PUT)
+            rc = 1;
+
+    case AnyP::PROTO_GOPHER:
+
+    case AnyP::PROTO_WAIS:
+
+    case AnyP::PROTO_WHOIS:
+        if (r->method == Http::METHOD_GET)
+            rc = 1;
+        else if (r->method == Http::METHOD_HEAD)
+            rc = 1;
+
+        break;
+
+    case AnyP::PROTO_HTTPS:
+#if USE_OPENSSL
+        rc = 1;
+#elif USE_GNUTLS
+        rc = 1;
+#else
+        /*
+        * Squid can't originate an SSL connection, so it should
+        * never receive an "https:" URL.  It should always be
+        * CONNECT instead.
+        */
+        rc = 0;
+#endif
+        break;
+
+    default:
+        break;
+    }
+
+    return rc;
+}
+
+/*
+ * Quick-n-dirty host extraction from a URL.  Steps:
+ *      Look for a colon
+ *      Skip any '/' after the colon
+ *      Copy the next SQUID_MAXHOSTNAMELEN bytes to host[]
+ *      Look for an ending '/' or ':' and terminate
+ *      Look for login info preceeded by '@'
+ */
+
+class URLHostName
+{
+
+public:
+    char * extract(char const *url);
+
+private:
+    static char Host [SQUIDHOSTNAMELEN];
+    void init(char const *);
+    void findHostStart();
+    void trimTrailingChars();
+    void trimAuth();
+    char const *hostStart;
+    char const *url;
+};
+
+char *
+urlHostname(const char *url)
+{
+    return URLHostName().extract(url);
+}
+
+char URLHostName::Host[SQUIDHOSTNAMELEN];
+
+void
+URLHostName::init(char const *aUrl)
+{
+    Host[0] = '\0';
+    url = aUrl;
+}
+
+void
+URLHostName::findHostStart()
+{
+    if (NULL == (hostStart = strchr(url, ':')))
+        return;
+
+    ++hostStart;
+
+    while (*hostStart != '\0' && *hostStart == '/')
+        ++hostStart;
+
+    if (*hostStart == ']')
+        ++hostStart;
+}
+
+void
+URLHostName::trimTrailingChars()
+{
+    char *t;
+
+    if ((t = strchr(Host, '/')))
+        *t = '\0';
+
+    if ((t = strrchr(Host, ':')))
+        *t = '\0';
+
+    if ((t = strchr(Host, ']')))
+        *t = '\0';
+}
+
+void
+URLHostName::trimAuth()
+{
+    char *t;
+
+    if ((t = strrchr(Host, '@'))) {
+        ++t;
+        memmove(Host, t, strlen(t) + 1);
+    }
+}
+
+char *
+URLHostName::extract(char const *aUrl)
+{
+    init(aUrl);
+    findHostStart();
+
+    if (hostStart == NULL)
+        return NULL;
+
+    xstrncpy(Host, hostStart, SQUIDHOSTNAMELEN);
+
+    trimTrailingChars();
+
+    trimAuth();
+
+    return Host;
+}
+
+AnyP::Uri::Uri(AnyP::UriScheme const &aScheme) :
+    scheme_(aScheme),
+    hostIsNumeric_(false),
+    port_(0)
+{
+    *host_=0;
+}
+
diff -u -r -N squid-4.0.25/src/anyp/Uri.h squid-4.1/src/anyp/Uri.h
--- squid-4.0.25/src/anyp/Uri.h	1970-01-01 12:00:00.000000000 +1200
+++ squid-4.1/src/anyp/Uri.h	2018-07-02 15:26:07.000000000 +1200
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SRC_ANYP_URI_H
+#define SQUID_SRC_ANYP_URI_H
+
+#include "anyp/UriScheme.h"
+#include "ip/Address.h"
+#include "rfc2181.h"
+#include "sbuf/SBuf.h"
+
+#include <iosfwd>
+
+class HttpRequestMethod;
+
+namespace AnyP
+{
+
+/**
+ * Represents a Uniform Resource Identifier.
+ * Can store both URL or URN representations.
+ *
+ * Governed by RFC 3986
+ */
+class Uri
+{
+    MEMPROXY_CLASS(Uri);
+
+public:
+    Uri() : hostIsNumeric_(false), port_(0) {*host_=0;}
+    Uri(AnyP::UriScheme const &aScheme);
+    Uri(const Uri &other) {
+        this->operator =(other);
+    }
+    Uri &operator =(const Uri &o) {
+        scheme_ = o.scheme_;
+        userInfo_ = o.userInfo_;
+        memcpy(host_, o.host_, sizeof(host_));
+        hostIsNumeric_ = o.hostIsNumeric_;
+        hostAddr_ = o.hostAddr_;
+        port_ = o.port_;
+        path_ = o.path_;
+        touch();
+        return *this;
+    }
+
+    void clear() {
+        scheme_=AnyP::PROTO_NONE;
+        hostIsNumeric_ = false;
+        *host_ = 0;
+        hostAddr_.setEmpty();
+        port_ = 0;
+        touch();
+    }
+    void touch(); ///< clear the cached URI display forms
+
+    bool parse(const HttpRequestMethod &, const char *url);
+
+    AnyP::UriScheme const & getScheme() const {return scheme_;}
+
+    /// convert the URL scheme to that given
+    void setScheme(const AnyP::ProtocolType &p, const char *str) {
+        scheme_ = AnyP::UriScheme(p, str);
+        touch();
+    }
+
+    void userInfo(const SBuf &s) {userInfo_=s; touch();}
+    const SBuf &userInfo() const {return userInfo_;}
+
+    void host(const char *src);
+    const char *host(void) const {return host_;}
+    int hostIsNumeric(void) const {return hostIsNumeric_;}
+    Ip::Address const & hostIP(void) const {return hostAddr_;}
+
+    void port(unsigned short p) {port_=p; touch();}
+    unsigned short port() const {return port_;}
+
+    void path(const char *p) {path_=p; touch();}
+    void path(const SBuf &p) {path_=p; touch();}
+    const SBuf &path() const;
+
+    /// the static '/' default URL-path
+    static const SBuf &SlashPath();
+
+    /// the static '*' pseudo-URI
+    static const SBuf &Asterisk();
+
+    /**
+     * The authority-form URI for currently stored values.
+     *
+     * As defined by RFC 7230 section 5.3.3 this form omits the
+     * userinfo@ field from RFC 3986 defined authority segment.
+     *
+     * \param requirePort when true the port will be included, otherwise
+     *                    port will be elided when it is the default for
+     *                    the current scheme.
+     */
+    SBuf &authority(bool requirePort = false) const;
+
+    /**
+     * The absolute-form URI for currently stored values.
+     *
+     * As defined by RFC 7230 section 5.3.3 this form omits the
+     * userinfo@ field from RFC 3986 defined authority segments
+     * when the protocol scheme is http: or https:.
+     */
+    SBuf &absolute() const;
+
+private:
+    void parseFinish(const AnyP::ProtocolType, const char *const, const char *const, const char *const, const SBuf &, const int);
+
+    /**
+     \par
+     * The scheme of this URL. This has the 'type code' smell about it.
+     * In future we may want to make the methods that dispatch based on
+     * the scheme virtual and have a class per protocol.
+     \par
+     * On the other hand, having Protocol as an explicit concept is useful,
+     * see for instance the ACLProtocol acl type. One way to represent this
+     * is to have one prototype URL with no host etc for each scheme,
+     * another is to have an explicit scheme class, and then each URL class
+     * could be a subclass of the scheme. Another way is one instance of
+     * a AnyP::UriScheme class instance for each URL scheme we support, and one
+     * class for each manner of treating the scheme : a Hierarchical URL, a
+     * non-hierarchical URL etc.
+     \par
+     * Deferring the decision, its a type code for now. RBC 20060507.
+     \par
+     * In order to make taking any of these routes easy, scheme is private,
+     * only settable at construction time, or with explicit setter
+     */
+    AnyP::UriScheme scheme_;
+
+    SBuf userInfo_; // aka 'URL-login'
+
+    // XXX: uses char[] instead of SBUf to reduce performance regressions
+    //      from c_str() since most code using this is not yet using SBuf
+    char host_[SQUIDHOSTNAMELEN];   ///< string representation of the URI authority name or IP
+    bool hostIsNumeric_;            ///< whether the authority 'host' is a raw-IP
+    Ip::Address hostAddr_;          ///< binary representation of the URI authority if it is a raw-IP
+
+    unsigned short port_;   ///< URL port
+
+    // XXX: for now includes query-string.
+    SBuf path_;     ///< URI path segment
+
+    // pre-assembled URI forms
+    mutable SBuf authorityHttp_;     ///< RFC 7230 section 5.3.3 authority, maybe without default-port
+    mutable SBuf authorityWithPort_; ///< RFC 7230 section 5.3.3 authority with explicit port
+    mutable SBuf absolute_;          ///< RFC 7230 section 5.3.2 absolute-URI
+};
+
+} // namespace AnyP
+
+inline std::ostream &
+operator <<(std::ostream &os, const AnyP::Uri &url)
+{
+    // none means explicit empty string for scheme.
+    if (url.getScheme() != AnyP::PROTO_NONE)
+        os << url.getScheme().image();
+    os << ":";
+
+    // no authority section on URN
+    if (url.getScheme() != AnyP::PROTO_URN)
+        os << "//" << url.authority();
+
+    // path is what it is - including absent
+    os << url.path();
+    return os;
+}
+
+/* Deprecated functions for Legacy code handling URLs */
+
+class HttpRequest;
+
+void urlInitialize(void);
+char *urlCanonicalClean(const HttpRequest *);
+const char *urlCanonicalFakeHttps(const HttpRequest * request);
+bool urlIsRelative(const char *);
+char *urlMakeAbsolute(const HttpRequest *, const char *);
+char *urlRInternal(const char *host, unsigned short port, const char *dir, const char *name);
+char *urlInternal(const char *dir, const char *name);
+
+enum MatchDomainNameFlags {
+    mdnNone = 0,
+    mdnHonorWildcards = 1 << 0,
+    mdnRejectSubsubDomains = 1 << 1
+};
+
+/**
+ * matchDomainName() matches a hostname (usually extracted from traffic)
+ * with a domainname when mdnNone or mdnRejectSubsubDomains flags are used
+ * according to the following rules:
+ *
+ *    HOST      |   DOMAIN    |   mdnNone | mdnRejectSubsubDomains
+ * -------------|-------------|-----------|-----------------------
+ *      foo.com |   foo.com   |     YES   |   YES
+ *     .foo.com |   foo.com   |     YES   |   YES
+ *    x.foo.com |   foo.com   |     NO    |   NO
+ *      foo.com |  .foo.com   |     YES   |   YES
+ *     .foo.com |  .foo.com   |     YES   |   YES
+ *    x.foo.com |  .foo.com   |     YES   |   YES
+ *   .x.foo.com |  .foo.com   |     YES   |   NO
+ *  y.x.foo.com |  .foo.com   |     YES   |   NO
+ *
+ * if mdnHonorWildcards flag is set then the matchDomainName() also accepts
+ * optional wildcards on hostname:
+ *
+ *    HOST      |    DOMAIN    |  MATCH?
+ * -------------|--------------|-------
+ *    *.foo.com |   x.foo.com  |   YES
+ *    *.foo.com |  .x.foo.com  |   YES
+ *    *.foo.com |    .foo.com  |   YES
+ *    *.foo.com |     foo.com  |   NO
+ *
+ * The combination of mdnHonorWildcards and mdnRejectSubsubDomains flags is
+ * supported.
+ *
+ * \retval 0 means the host matches the domain
+ * \retval 1 means the host is greater than the domain
+ * \retval -1 means the host is less than the domain
+ */
+int matchDomainName(const char *host, const char *domain, uint flags = mdnNone);
+int urlCheckRequest(const HttpRequest *);
+char *urlHostname(const char *url);
+void urlExtMethodConfigure(void);
+
+#endif /* SQUID_SRC_ANYP_URI_H */
+
diff -u -r -N squid-4.0.25/src/auth/basic/DB/basic_db_auth.8 squid-4.1/src/auth/basic/DB/basic_db_auth.8
--- squid-4.0.25/src/auth/basic/DB/basic_db_auth.8	2018-06-12 04:56:19.000000000 +1200
+++ squid-4.1/src/auth/basic/DB/basic_db_auth.8	2018-07-02 15:39:07.000000000 +1200
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_DB_AUTH 8"
-.TH BASIC_DB_AUTH 8 "2018-06-11" "perl v5.26.2" "User Contributed Perl Documentation"
+.TH BASIC_DB_AUTH 8 "2018-07-02" "perl v5.26.2" "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-4.0.25/src/auth/basic/POP3/basic_pop3_auth.8 squid-4.1/src/auth/basic/POP3/basic_pop3_auth.8
--- squid-4.0.25/src/auth/basic/POP3/basic_pop3_auth.8	2018-06-12 04:56:20.000000000 +1200
+++ squid-4.1/src/auth/basic/POP3/basic_pop3_auth.8	2018-07-02 15:39:07.000000000 +1200
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_POP3_AUTH 8"
-.TH BASIC_POP3_AUTH 8 "2018-06-11" "perl v5.26.2" "User Contributed Perl Documentation"
+.TH BASIC_POP3_AUTH 8 "2018-07-02" "perl v5.26.2" "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-4.0.25/src/carp.cc squid-4.1/src/carp.cc
--- squid-4.0.25/src/carp.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/carp.cc	2018-07-02 15:26:07.000000000 +1200
@@ -15,7 +15,6 @@
 #include "neighbors.h"
 #include "SquidConfig.h"
 #include "Store.h"
-#include "URL.h"
 
 #include <cmath>
 
diff -u -r -N squid-4.0.25/src/clients/Client.cc squid-4.1/src/clients/Client.cc
--- squid-4.0.25/src/clients/Client.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/clients/Client.cc	2018-07-02 15:26:07.000000000 +1200
@@ -25,7 +25,6 @@
 #include "StatCounters.h"
 #include "Store.h"
 #include "tools.h"
-#include "URL.h"
 
 #if USE_ADAPTATION
 #include "adaptation/AccessCheck.h"
diff -u -r -N squid-4.0.25/src/clients/FtpGateway.cc squid-4.1/src/clients/FtpGateway.cc
--- squid-4.0.25/src/clients/FtpGateway.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/clients/FtpGateway.cc	2018-07-02 15:26:07.000000000 +1200
@@ -38,7 +38,6 @@
 #include "StatCounters.h"
 #include "Store.h"
 #include "tools.h"
-#include "URL.h"
 #include "util.h"
 #include "wordlist.h"
 
@@ -2289,8 +2288,7 @@
     ferr.ftp.cwd_msg = xstrdup(cwd_message.size()? cwd_message.termedBuf() : "");
     ferr.ftp.server_msg = ctrl.message;
     ctrl.message = NULL;
-    entry->replaceHttpReply( ferr.BuildHttpReply() );
-    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
+    entry->replaceHttpReply(ferr.BuildHttpReply());
     entry->flush();
     entry->unlock("Ftp::Gateway");
 }
@@ -2563,8 +2561,6 @@
 
     assert(entry->isEmpty());
 
-    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
-
     entry->buffer();    /* released when done processing current data payload */
 
     SBuf urlPath = request->url.path();
diff -u -r -N squid-4.0.25/src/clients/FtpRelay.cc squid-4.1/src/clients/FtpRelay.cc
--- squid-4.0.25/src/clients/FtpRelay.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/clients/FtpRelay.cc	2018-07-02 15:26:07.000000000 +1200
@@ -292,7 +292,6 @@
     const Http::StatusCode httpStatus = failedHttpStatus(error);
     HttpReply *const reply = createHttpReply(httpStatus);
     entry->replaceHttpReply(reply);
-    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
     fwd->request->detailError(error, xerrno);
 }
 
@@ -375,7 +374,6 @@
 Ftp::Relay::forwardReply()
 {
     assert(entry->isEmpty());
-    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
 
     HttpReply *const reply = createHttpReply(Http::scNoContent);
     reply->sources |= HttpMsg::srcFtp;
@@ -453,7 +451,6 @@
     HttpReply *const reply = createHttpReply(Http::scOkay, -1);
     reply->sources |= HttpMsg::srcFtp;
 
-    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
     setVirginReply(reply);
     adaptOrFinalizeReply();
 
diff -u -r -N squid-4.0.25/src/client_side.cc squid-4.1/src/client_side.cc
--- squid-4.0.25/src/client_side.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/client_side.cc	2018-07-02 15:26:07.000000000 +1200
@@ -113,7 +113,6 @@
 #include "Store.h"
 #include "TimeOrTag.h"
 #include "tools.h"
-#include "URL.h"
 
 #if USE_AUTH
 #include "auth/UserRequest.h"
diff -u -r -N squid-4.0.25/src/client_side_reply.cc squid-4.1/src/client_side_reply.cc
--- squid-4.0.25/src/client_side_reply.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/client_side_reply.cc	2018-07-02 15:26:07.000000000 +1200
@@ -37,7 +37,6 @@
 #include "Store.h"
 #include "StrList.h"
 #include "tools.h"
-#include "URL.h"
 #if USE_AUTH
 #include "auth/UserRequest.h"
 #endif
diff -u -r -N squid-4.0.25/src/client_side_request.cc squid-4.1/src/client_side_request.cc
--- squid-4.0.25/src/client_side_request.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/client_side_request.cc	2018-07-02 15:26:07.000000000 +1200
@@ -53,7 +53,6 @@
 #include "Store.h"
 #include "StrList.h"
 #include "tools.h"
-#include "URL.h"
 #include "wordlist.h"
 #if USE_AUTH
 #include "auth/UserRequest.h"
@@ -1264,7 +1263,7 @@
 
             // prevent broken helpers causing too much damage. If old URL == new URL skip the re-write.
             if (urlNote != NULL && strcmp(urlNote, http->uri)) {
-                URL tmpUrl;
+                AnyP::Uri tmpUrl;
                 if (tmpUrl.parse(old_request->method, urlNote)) {
                     HttpRequest *new_request = old_request->clone();
                     new_request->url = tmpUrl;
@@ -1953,7 +1952,6 @@
         assert(repContext);
         repContext->createStoreEntry(request->method, request->flags);
 
-        EBIT_CLR(storeEntry()->flags, ENTRY_FWD_HDR_WAIT);
         request_satisfaction_mode = true;
         request_satisfaction_offset = 0;
         storeEntry()->replaceHttpReply(new_rep);
diff -u -r -N squid-4.0.25/src/enums.h squid-4.1/src/enums.h
--- squid-4.0.25/src/enums.h	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/enums.h	2018-07-02 15:26:07.000000000 +1200
@@ -75,12 +75,31 @@
 enum {
     ENTRY_SPECIAL,
     ENTRY_REVALIDATE_ALWAYS,
+
+    /// Tiny Store writes are likely. The writes should be aggregated together
+    /// before Squid announces the new content availability to the store
+    /// clients. For example, forming a cached HTTP response header may result
+    /// in dozens of StoreEntry::write() calls, many of which adding as little
+    /// as two bytes. Sharing those small writes with the store clients
+    /// increases overhead, especially because the client code can do nothing
+    /// useful with the written content until the whole response header is
+    /// stored. Might be combined with ENTRY_FWD_HDR_WAIT. TODO: Rename to
+    /// ENTRY_DELAY_WHILE_COALESCING to emphasize the difference from and
+    /// similarity with ENTRY_FWD_HDR_WAIT.
     DELAY_SENDING,
     RELEASE_REQUEST, ///< prohibits making the key public
     REFRESH_REQUEST,
     ENTRY_REVALIDATE_STALE,
     ENTRY_DISPATCHED,
     KEY_PRIVATE,
+
+    /// The current entry response may change. The contents of an entry in this
+    /// state must not be shared with its store clients. For example, Squid
+    /// receives (and buffers) an HTTP/504 response but may decide to retry that
+    /// transaction to receive a successful response from another server
+    /// instead. Might be combined with DELAY_SENDING. TODO: Rename to
+    /// ENTRY_DELAY_WHILE_WOBBLING to emphasize the difference from and
+    /// similarity with DELAY_SENDING.
     ENTRY_FWD_HDR_WAIT,
     ENTRY_NEGCACHED,
     ENTRY_VALIDATED,
diff -u -r -N squid-4.0.25/src/errorpage.cc squid-4.1/src/errorpage.cc
--- squid-4.0.25/src/errorpage.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/errorpage.cc	2018-07-02 15:26:07.000000000 +1200
@@ -27,7 +27,6 @@
 #include "SquidConfig.h"
 #include "Store.h"
 #include "tools.h"
-#include "URL.h"
 #include "wordlist.h"
 #if USE_AUTH
 #include "auth/UserRequest.h"
diff -u -r -N squid-4.0.25/src/external_acl.cc squid-4.1/src/external_acl.cc
--- squid-4.0.25/src/external_acl.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/external_acl.cc	2018-07-02 15:26:07.000000000 +1200
@@ -35,7 +35,6 @@
 #include "SquidTime.h"
 #include "Store.h"
 #include "tools.h"
-#include "URL.h"
 #include "wordlist.h"
 #if USE_OPENSSL
 #include "ssl/ServerBump.h"
diff -u -r -N squid-4.0.25/src/format/Format.cc squid-4.1/src/format/Format.cc
--- squid-4.0.25/src/format/Format.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/format/Format.cc	2018-07-02 15:26:07.000000000 +1200
@@ -27,7 +27,6 @@
 #include "SquidTime.h"
 #include "Store.h"
 #include "tools.h"
-#include "URL.h"
 #if USE_OPENSSL
 #include "ssl/ErrorDetail.h"
 #include "ssl/ServerBump.h"
diff -u -r -N squid-4.0.25/src/FwdState.cc squid-4.1/src/FwdState.cc
--- squid-4.0.25/src/FwdState.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/FwdState.cc	2018-07-02 15:26:07.000000000 +1200
@@ -143,7 +143,6 @@
     HTTPMSGLOCK(request);
     serverDestinations.reserve(Config.forward_max_tries);
     e->lock("FwdState");
-    EBIT_SET(e->flags, ENTRY_FWD_HDR_WAIT);
     flags.connected_okay = false;
     flags.dont_retry = false;
     flags.forward_completed = false;
@@ -258,7 +257,6 @@
             }
 #endif
         } else {
-            EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
             entry->complete();
             entry->releaseRequest();
         }
@@ -528,7 +526,6 @@
             debugs(17, 3, HERE << "server FD " << serverConnection()->fd << " not re-forwarding status " << entry->getReply()->sline.status());
         else
             debugs(17, 3, HERE << "server (FD closed) not re-forwarding status " << entry->getReply()->sline.status());
-        EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
         entry->complete();
 
         if (!Comm::IsConnOpen(serverConn))
diff -u -r -N squid-4.0.25/src/gopher.cc squid-4.1/src/gopher.cc
--- squid-4.0.25/src/gopher.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/gopher.cc	2018-07-02 15:26:07.000000000 +1200
@@ -241,7 +241,6 @@
     }
 
     assert(entry->isEmpty());
-    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
 
     HttpReply *reply = new HttpReply;
     entry->buffer();
diff -u -r -N squid-4.0.25/src/htcp.cc squid-4.1/src/htcp.cc
--- squid-4.0.25/src/htcp.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/htcp.cc	2018-07-02 15:26:07.000000000 +1200
@@ -35,7 +35,6 @@
 #include "store_key_md5.h"
 #include "StoreClient.h"
 #include "tools.h"
-#include "URL.h"
 
 typedef struct _Countstr Countstr;
 
diff -u -r -N squid-4.0.25/src/http/url_rewriters/LFS/url_lfs_rewrite.8 squid-4.1/src/http/url_rewriters/LFS/url_lfs_rewrite.8
--- squid-4.0.25/src/http/url_rewriters/LFS/url_lfs_rewrite.8	2018-06-12 04:56:20.000000000 +1200
+++ squid-4.1/src/http/url_rewriters/LFS/url_lfs_rewrite.8	2018-07-02 15:39:08.000000000 +1200
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "URL_LFS_REWRITE 8"
-.TH URL_LFS_REWRITE 8 "2018-06-11" "perl v5.26.2" "User Contributed Perl Documentation"
+.TH URL_LFS_REWRITE 8 "2018-07-02" "perl v5.26.2" "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-4.0.25/src/http.cc squid-4.1/src/http.cc
--- squid-4.0.25/src/http.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/http.cc	2018-07-02 15:26:07.000000000 +1200
@@ -56,7 +56,6 @@
 #include "Store.h"
 #include "StrList.h"
 #include "tools.h"
-#include "URL.h"
 #include "util.h"
 
 #if USE_AUTH
@@ -928,8 +927,8 @@
             // TODO: check whether such responses are shareable.
             // Do not share for now.
             entry->makePrivate(false);
-            if (!fwd->reforwardableStatus(rep->sline.status()))
-                EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
+            if (fwd->reforwardableStatus(rep->sline.status()))
+                EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT);
             varyFailure = true;
         } else {
             entry->mem_obj->vary_headers = vary;
@@ -947,8 +946,8 @@
          * If its not a reply that we will re-forward, then
          * allow the client to get it.
          */
-        if (!fwd->reforwardableStatus(rep->sline.status()))
-            EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
+        if (fwd->reforwardableStatus(rep->sline.status()))
+            EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT);
 
         ReuseDecision decision(entry, statusCode);
 
diff -u -r -N squid-4.0.25/src/HttpRequest.cc squid-4.1/src/HttpRequest.cc
--- squid-4.0.25/src/HttpRequest.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/HttpRequest.cc	2018-07-02 15:26:07.000000000 +1200
@@ -30,7 +30,6 @@
 #include "sbuf/StringConvert.h"
 #include "SquidConfig.h"
 #include "Store.h"
-#include "URL.h"
 
 #if USE_AUTH
 #include "auth/UserRequest.h"
diff -u -r -N squid-4.0.25/src/HttpRequest.h squid-4.1/src/HttpRequest.h
--- squid-4.0.25/src/HttpRequest.h	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/HttpRequest.h	2018-07-02 15:26:07.000000000 +1200
@@ -9,6 +9,7 @@
 #ifndef SQUID_HTTPREQUEST_H
 #define SQUID_HTTPREQUEST_H
 
+#include "anyp/Uri.h"
 #include "base/CbcPointer.h"
 #include "dns/forward.h"
 #include "err_type.h"
@@ -18,7 +19,6 @@
 #include "MasterXaction.h"
 #include "Notes.h"
 #include "RequestFlags.h"
-#include "URL.h"
 
 #if USE_AUTH
 #include "auth/UserRequest.h"
@@ -100,7 +100,7 @@
 
 public:
     HttpRequestMethod method;
-    URL url; ///< the request URI
+    AnyP::Uri url; ///< the request URI
 
 private:
 #if USE_ADAPTATION
diff -u -r -N squid-4.0.25/src/icmp/net_db.cc squid-4.1/src/icmp/net_db.cc
--- squid-4.0.25/src/icmp/net_db.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/icmp/net_db.cc	2018-07-02 15:26:07.000000000 +1200
@@ -38,7 +38,6 @@
 #include "Store.h"
 #include "StoreClient.h"
 #include "tools.h"
-#include "URL.h"
 #include "wordlist.h"
 
 #if HAVE_SYS_STAT_H
@@ -1095,7 +1094,7 @@
 }
 
 void
-netdbUpdatePeer(const URL &url, CachePeer * e, int irtt, int ihops)
+netdbUpdatePeer(const AnyP::Uri &url, CachePeer *e, int irtt, int ihops)
 {
 #if USE_ICMP
     netdbEntry *n;
diff -u -r -N squid-4.0.25/src/icmp/net_db.h squid-4.1/src/icmp/net_db.h
--- squid-4.0.25/src/icmp/net_db.h	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/icmp/net_db.h	2018-07-02 15:26:07.000000000 +1200
@@ -9,6 +9,7 @@
 #ifndef ICMP_NET_DB_H
 #define ICMP_NET_DB_H
 
+#include "anyp/forward.h"
 #include "hash.h"
 #include "ip/forward.h"
 #include "mem/forward.h"
@@ -17,7 +18,6 @@
 class HttpRequest;
 class netdbEntry;
 class StoreEntry;
-class URL;
 
 class net_db_name:
     public hash_link /* must be first */
@@ -73,7 +73,7 @@
 void netdbFreeMemory(void);
 int netdbHostHops(const char *host);
 int netdbHostRtt(const char *host);
-void netdbUpdatePeer(const URL &, CachePeer * e, int rtt, int hops);
+void netdbUpdatePeer(const AnyP::Uri &, CachePeer *, int rtt, int hops);
 
 void netdbDeleteAddrNetwork(Ip::Address &addr);
 void netdbBinaryExchange(StoreEntry *);
diff -u -r -N squid-4.0.25/src/internal.cc squid-4.1/src/internal.cc
--- squid-4.0.25/src/internal.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/internal.cc	2018-07-02 15:26:07.000000000 +1200
@@ -20,7 +20,6 @@
 #include "SquidTime.h"
 #include "Store.h"
 #include "tools.h"
-#include "URL.h"
 #include "util.h"
 #include "wordlist.h"
 
@@ -108,7 +107,7 @@
                 strlen(lc_host) - 1);
 
     /* build URI */
-    URL tmp(AnyP::PROTO_HTTP);
+    AnyP::Uri tmp(AnyP::PROTO_HTTP);
     tmp.host(lc_host);
     if (port)
         tmp.port(port);
diff -u -r -N squid-4.0.25/src/ipc/Forwarder.cc squid-4.1/src/ipc/Forwarder.cc
--- squid-4.0.25/src/ipc/Forwarder.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/ipc/Forwarder.cc	2018-07-02 15:26:07.000000000 +1200
@@ -87,8 +87,10 @@
 {
     debugs(54, 3, HERE);
     request->requestId = 0;
-    // Do not clear ENTRY_FWD_HDR_WAIT or do entry->complete() because
-    // it will trigger our client side processing. Let job cleanup close.
+    // Do not do entry->complete() because it will trigger our client side
+    // processing when we no longer own the client-Squid connection.
+    // Let job cleanup close the client-Squid connection that Coordinator
+    // now owns.
 }
 
 /// Ipc::Forwarder::requestTimedOut wrapper
diff -u -r -N squid-4.0.25/src/log/DB/log_db_daemon.8 squid-4.1/src/log/DB/log_db_daemon.8
--- squid-4.0.25/src/log/DB/log_db_daemon.8	2018-06-12 04:56:21.000000000 +1200
+++ squid-4.1/src/log/DB/log_db_daemon.8	2018-07-02 15:39:08.000000000 +1200
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "LOG_DB_DAEMON 8"
-.TH LOG_DB_DAEMON 8 "2018-06-11" "perl v5.26.2" "User Contributed Perl Documentation"
+.TH LOG_DB_DAEMON 8 "2018-07-02" "perl v5.26.2" "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-4.0.25/src/main.cc squid-4.1/src/main.cc
--- squid-4.0.25/src/main.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/main.cc	2018-07-02 15:26:07.000000000 +1200
@@ -78,7 +78,6 @@
 #include "StoreFileSystem.h"
 #include "tools.h"
 #include "unlinkd.h"
-#include "URL.h"
 #include "wccp.h"
 #include "wccp2.h"
 #include "WinSvc.h"
diff -u -r -N squid-4.0.25/src/Makefile.am squid-4.1/src/Makefile.am
--- squid-4.0.25/src/Makefile.am	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/Makefile.am	2018-07-02 15:26:07.000000000 +1200
@@ -473,8 +473,6 @@
 	tunnel.cc \
 	typedefs.h \
 	$(UNLINKDSOURCE) \
-	url.cc \
-	URL.h \
 	urn.h \
 	urn.cc \
 	wccp.h \
@@ -997,7 +995,7 @@
 	tests/testHttpReply.cc \
 	tests/testHttpReply.h \
 	tests/stub_time.cc \
-	url.cc \
+	tests/stub_libanyp.cc \
 	wordlist.h \
 	wordlist.cc
 nodist_tests_testHttpReply_SOURCES=\
@@ -1120,8 +1118,7 @@
 	tests/testACLMaxUserIP.cc \
 	tests/testACLMaxUserIP.h \
 	tests/stub_time.cc \
-	url.cc \
-	URL.h \
+	tests/stub_libanyp.cc \
 	MemBuf.cc \
 	wordlist.h \
 	wordlist.cc
@@ -1373,7 +1370,7 @@
 	tests/stub_SwapDir.cc \
 	MemStore.cc \
 	$(UNLINKDSOURCE) \
-	url.cc \
+	tests/stub_libanyp.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -1557,7 +1554,7 @@
 	tests/testStoreSupport.h \
 	tests/stub_time.cc \
 	$(UNLINKDSOURCE) \
-	url.cc \
+	tests/stub_libanyp.cc \
 	$(WIN32_SOURCE) \
 	wordlist.h \
 	wordlist.cc \
@@ -1807,7 +1804,7 @@
 	tests/stub_tunnel.cc \
 	MemStore.cc \
 	$(UNLINKDSOURCE) \
-	url.cc \
+	tests/stub_libanyp.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -2043,7 +2040,7 @@
 	tests/stub_tunnel.cc \
 	MemStore.cc \
 	$(UNLINKDSOURCE) \
-	url.cc \
+	tests/stub_libanyp.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -2274,7 +2271,7 @@
 	tools.cc \
 	tests/stub_tunnel.cc \
 	$(UNLINKDSOURCE) \
-	url.cc \
+	tests/stub_libanyp.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -2379,6 +2376,7 @@
 	tests/testHttp1Parser.cc \
 	tests/testHttp1Parser.h \
 	tests/stub_time.cc \
+	tests/stub_libanyp.cc \
 	wordlist.h \
 	wordlist.cc
 nodist_tests_testHttp1Parser_SOURCES = \
@@ -2577,7 +2575,6 @@
 	tests/stub_tunnel.cc \
 	tests/stub_SwapDir.cc \
 	MemStore.cc \
-	url.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -2815,7 +2812,7 @@
 	tests/TestSwapDir.cc \
 	tests/TestSwapDir.h \
 	tests/stub_time.cc \
-	url.cc \
+	tests/stub_libanyp.cc \
 	wordlist.h \
 	wordlist.cc
 
@@ -3014,7 +3011,7 @@
 	HttpHdrCc.cci \
 	HttpHdrSc.cc \
 	HttpHdrScTarget.cc \
-	url.cc \
+	tests/stub_libanyp.cc \
 	StatCounters.h \
 	StatCounters.cc \
 	StatHist.h \
@@ -3214,7 +3211,7 @@
 	tools.h \
 	tests/stub_tools.cc \
 	time.cc \
-	url.cc \
+	tests/stub_libanyp.cc \
 	wordlist.h \
 	wordlist.cc \
 	$(DELAY_POOL_SOURCE) \
@@ -3441,7 +3438,6 @@
 	tools.h \
 	tools.cc \
 	tests/stub_tunnel.cc \
-	url.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
diff -u -r -N squid-4.0.25/src/Makefile.in squid-4.1/src/Makefile.in
--- squid-4.0.25/src/Makefile.in	2018-06-12 04:47:59.000000000 +1200
+++ squid-4.1/src/Makefile.in	2018-07-02 15:32:02.000000000 +1200
@@ -308,10 +308,10 @@
 	StoreStats.h StoreSwapLogData.cc StoreSwapLogData.h \
 	swap_log_op.h Transients.cc Transients.h MemStore.cc \
 	MemStore.h time.cc TimeOrTag.h tools.h tools.cc tunnel.cc \
-	typedefs.h unlinkd.h unlinkd.cc url.cc URL.h urn.h urn.cc \
-	wccp.h wccp.cc wccp2.h wccp2.cc whois.h whois.cc wordlist.h \
-	wordlist.cc XactionInitiator.h XactionInitiator.cc win32.cc \
-	WinSvc.cc LoadableModule.h LoadableModule.cc LoadableModules.h \
+	typedefs.h unlinkd.h unlinkd.cc urn.h urn.cc wccp.h wccp.cc \
+	wccp2.h wccp2.cc whois.h whois.cc wordlist.h wordlist.cc \
+	XactionInitiator.h XactionInitiator.cc win32.cc WinSvc.cc \
+	LoadableModule.h LoadableModule.cc LoadableModules.h \
 	LoadableModules.cc
 am__objects_1 = AclRegs.$(OBJEXT) AuthReg.$(OBJEXT)
 am__objects_2 = delay_pools.$(OBJEXT) DelayId.$(OBJEXT) \
@@ -384,7 +384,7 @@
 	$(am__objects_11) StoreStats.$(OBJEXT) \
 	StoreSwapLogData.$(OBJEXT) Transients.$(OBJEXT) \
 	MemStore.$(OBJEXT) time.$(OBJEXT) tools.$(OBJEXT) \
-	tunnel.$(OBJEXT) $(am__objects_12) url.$(OBJEXT) urn.$(OBJEXT) \
+	tunnel.$(OBJEXT) $(am__objects_12) urn.$(OBJEXT) \
 	wccp.$(OBJEXT) wccp2.$(OBJEXT) whois.$(OBJEXT) \
 	wordlist.$(OBJEXT) XactionInitiator.$(OBJEXT) \
 	$(am__objects_13) $(am__objects_14) $(am__objects_16)
@@ -480,7 +480,8 @@
 	tests/stub_store_swapout.$(OBJEXT) tests/stub_tools.$(OBJEXT) \
 	tests/stub_cache_manager.$(OBJEXT) tests/stub_UdsOp.$(OBJEXT) \
 	tests/testACLMaxUserIP.$(OBJEXT) tests/stub_time.$(OBJEXT) \
-	url.$(OBJEXT) MemBuf.$(OBJEXT) wordlist.$(OBJEXT)
+	tests/stub_libanyp.$(OBJEXT) MemBuf.$(OBJEXT) \
+	wordlist.$(OBJEXT)
 am__objects_18 = test_tools.$(OBJEXT) globals.$(OBJEXT)
 nodist_tests_testACLMaxUserIP_OBJECTS = $(am__objects_18)
 tests_testACLMaxUserIP_OBJECTS = $(am_tests_testACLMaxUserIP_OBJECTS) \
@@ -569,8 +570,8 @@
 	StoreIOState.cc tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
 	StoreSwapLogData.cc tools.h tools.cc Transients.cc \
 	tests/stub_tunnel.cc tests/stub_SwapDir.cc MemStore.cc \
-	unlinkd.h unlinkd.cc url.cc urn.h urn.cc wccp2.h \
-	tests/stub_wccp2.cc whois.h tests/stub_whois.cc \
+	unlinkd.h unlinkd.cc tests/stub_libanyp.cc urn.h urn.cc \
+	wccp2.h tests/stub_wccp2.cc whois.h tests/stub_whois.cc \
 	FadingCounter.cc win32.cc wordlist.h wordlist.cc
 am_tests_testCacheManager_OBJECTS = AccessLogEntry.$(OBJEXT) \
 	debug.$(OBJEXT) RequestFlags.$(OBJEXT) HttpRequest.$(OBJEXT) \
@@ -626,7 +627,7 @@
 	StoreSwapLogData.$(OBJEXT) tools.$(OBJEXT) \
 	Transients.$(OBJEXT) tests/stub_tunnel.$(OBJEXT) \
 	tests/stub_SwapDir.$(OBJEXT) MemStore.$(OBJEXT) \
-	$(am__objects_12) url.$(OBJEXT) urn.$(OBJEXT) \
+	$(am__objects_12) tests/stub_libanyp.$(OBJEXT) urn.$(OBJEXT) \
 	tests/stub_wccp2.$(OBJEXT) tests/stub_whois.$(OBJEXT) \
 	FadingCounter.$(OBJEXT) $(am__objects_13) wordlist.$(OBJEXT)
 nodist_tests_testCacheManager_OBJECTS = $(am__objects_17)
@@ -733,8 +734,8 @@
 	tests/stub_store_rebuild.cc tests/stub_UdsOp.cc \
 	tests/testDiskIO.cc tests/testDiskIO.h \
 	tests/testStoreSupport.cc tests/testStoreSupport.h \
-	tests/stub_time.cc unlinkd.h unlinkd.cc url.cc win32.cc \
-	wordlist.h wordlist.cc tools.h tests/stub_tools.cc
+	tests/stub_time.cc unlinkd.h unlinkd.cc tests/stub_libanyp.cc \
+	win32.cc wordlist.h wordlist.cc tools.h tests/stub_tools.cc
 am_tests_testDiskIO_OBJECTS = AccessLogEntry.$(OBJEXT) \
 	tests/stub_CacheDigest.$(OBJEXT) cbdata.$(OBJEXT) \
 	tests/stub_CollapsedForwarding.$(OBJEXT) \
@@ -780,9 +781,9 @@
 	tests/stub_store_stats.$(OBJEXT) \
 	tests/stub_store_rebuild.$(OBJEXT) tests/stub_UdsOp.$(OBJEXT) \
 	tests/testDiskIO.$(OBJEXT) tests/testStoreSupport.$(OBJEXT) \
-	tests/stub_time.$(OBJEXT) $(am__objects_12) url.$(OBJEXT) \
-	$(am__objects_13) wordlist.$(OBJEXT) \
-	tests/stub_tools.$(OBJEXT)
+	tests/stub_time.$(OBJEXT) $(am__objects_12) \
+	tests/stub_libanyp.$(OBJEXT) $(am__objects_13) \
+	wordlist.$(OBJEXT) tests/stub_tools.$(OBJEXT)
 nodist_tests_testDiskIO_OBJECTS = $(am__objects_18) \
 	SquidMath.$(OBJEXT) swap_log_op.$(OBJEXT)
 tests_testDiskIO_OBJECTS = $(am_tests_testDiskIO_OBJECTS) \
@@ -873,9 +874,9 @@
 	tests/stub_libauth.cc tests/stub_libdiskio.cc \
 	tests/stub_libeui.cc tests/stub_store_stats.cc time.cc tools.h \
 	tools.cc Transients.cc tests/stub_tunnel.cc MemStore.cc \
-	unlinkd.h unlinkd.cc url.cc urn.h urn.cc wccp2.h \
-	tests/stub_wccp2.cc whois.h tests/stub_whois.cc win32.cc \
-	wordlist.h wordlist.cc
+	unlinkd.h unlinkd.cc tests/stub_libanyp.cc urn.h urn.cc \
+	wccp2.h tests/stub_wccp2.cc whois.h tests/stub_whois.cc \
+	win32.cc wordlist.h wordlist.cc
 am_tests_testEvent_OBJECTS = AccessLogEntry.$(OBJEXT) \
 	BodyPipe.$(OBJEXT) tests/stub_CacheDigest.$(OBJEXT) \
 	cache_cf.$(OBJEXT) CachePeer.$(OBJEXT) cache_manager.$(OBJEXT) \
@@ -930,7 +931,7 @@
 	tests/stub_store_stats.$(OBJEXT) time.$(OBJEXT) \
 	tools.$(OBJEXT) Transients.$(OBJEXT) \
 	tests/stub_tunnel.$(OBJEXT) MemStore.$(OBJEXT) \
-	$(am__objects_12) url.$(OBJEXT) urn.$(OBJEXT) \
+	$(am__objects_12) tests/stub_libanyp.$(OBJEXT) urn.$(OBJEXT) \
 	tests/stub_wccp2.$(OBJEXT) tests/stub_whois.$(OBJEXT) \
 	$(am__objects_13) wordlist.$(OBJEXT)
 nodist_tests_testEvent_OBJECTS = $(am__objects_17)
@@ -1012,8 +1013,9 @@
 	tests/stub_libeui.cc tests/stub_libsecurity.cc \
 	tests/stub_store_stats.cc time.cc tools.h tools.cc \
 	Transients.cc tests/stub_tunnel.cc MemStore.cc unlinkd.h \
-	unlinkd.cc url.cc urn.h urn.cc wccp2.h tests/stub_wccp2.cc \
-	whois.h tests/stub_whois.cc win32.cc wordlist.h wordlist.cc
+	unlinkd.cc tests/stub_libanyp.cc urn.h urn.cc wccp2.h \
+	tests/stub_wccp2.cc whois.h tests/stub_whois.cc win32.cc \
+	wordlist.h wordlist.cc
 am_tests_testEventLoop_OBJECTS = AccessLogEntry.$(OBJEXT) \
 	BodyPipe.$(OBJEXT) tests/stub_CacheDigest.$(OBJEXT) \
 	cache_manager.$(OBJEXT) cache_cf.$(OBJEXT) CachePeer.$(OBJEXT) \
@@ -1068,7 +1070,7 @@
 	tests/stub_store_stats.$(OBJEXT) time.$(OBJEXT) \
 	tools.$(OBJEXT) Transients.$(OBJEXT) \
 	tests/stub_tunnel.$(OBJEXT) MemStore.$(OBJEXT) \
-	$(am__objects_12) url.$(OBJEXT) urn.$(OBJEXT) \
+	$(am__objects_12) tests/stub_libanyp.$(OBJEXT) urn.$(OBJEXT) \
 	tests/stub_wccp2.$(OBJEXT) tests/stub_whois.$(OBJEXT) \
 	$(am__objects_13) wordlist.$(OBJEXT)
 nodist_tests_testEventLoop_OBJECTS = $(am__objects_17)
@@ -1106,7 +1108,7 @@
 	tests/stub_stmem.$(OBJEXT) tests/stub_store.$(OBJEXT) \
 	tests/stub_store_stats.$(OBJEXT) tests/stub_tools.$(OBJEXT) \
 	tests/testHttp1Parser.$(OBJEXT) tests/stub_time.$(OBJEXT) \
-	wordlist.$(OBJEXT)
+	tests/stub_libanyp.$(OBJEXT) wordlist.$(OBJEXT)
 nodist_tests_testHttp1Parser_OBJECTS = $(am__objects_18)
 tests_testHttp1Parser_OBJECTS = $(am_tests_testHttp1Parser_OBJECTS) \
 	$(nodist_tests_testHttp1Parser_OBJECTS)
@@ -1143,7 +1145,8 @@
 	tests/stub_StatHist.$(OBJEXT) tests/stub_store.$(OBJEXT) \
 	tests/stub_store_stats.$(OBJEXT) tests/stub_tools.$(OBJEXT) \
 	tests/stub_HttpRequest.$(OBJEXT) tests/testHttpReply.$(OBJEXT) \
-	tests/stub_time.$(OBJEXT) url.$(OBJEXT) wordlist.$(OBJEXT)
+	tests/stub_time.$(OBJEXT) tests/stub_libanyp.$(OBJEXT) \
+	wordlist.$(OBJEXT)
 nodist_tests_testHttpReply_OBJECTS = $(am__objects_18)
 tests_testHttpReply_OBJECTS = $(am_tests_testHttpReply_OBJECTS) \
 	$(nodist_tests_testHttpReply_OBJECTS)
@@ -1216,7 +1219,7 @@
 	StoreIOState.cc tests/stub_StoreMeta.cc StoreMetaUnpacker.cc \
 	StoreSwapLogData.cc StrList.h StrList.cc event.cc tools.h \
 	tools.cc Transients.cc tests/stub_tunnel.cc \
-	tests/stub_SwapDir.cc MemStore.cc url.cc urn.h urn.cc wccp2.h \
+	tests/stub_SwapDir.cc MemStore.cc urn.h urn.cc wccp2.h \
 	tests/stub_wccp2.cc whois.h tests/stub_whois.cc \
 	FadingCounter.cc win32.cc wordlist.h wordlist.cc
 am_tests_testHttpRequest_OBJECTS = AccessLogEntry.$(OBJEXT) \
@@ -1275,9 +1278,9 @@
 	StoreSwapLogData.$(OBJEXT) StrList.$(OBJEXT) event.$(OBJEXT) \
 	tools.$(OBJEXT) Transients.$(OBJEXT) \
 	tests/stub_tunnel.$(OBJEXT) tests/stub_SwapDir.$(OBJEXT) \
-	MemStore.$(OBJEXT) url.$(OBJEXT) urn.$(OBJEXT) \
-	tests/stub_wccp2.$(OBJEXT) tests/stub_whois.$(OBJEXT) \
-	FadingCounter.$(OBJEXT) $(am__objects_13) wordlist.$(OBJEXT)
+	MemStore.$(OBJEXT) urn.$(OBJEXT) tests/stub_wccp2.$(OBJEXT) \
+	tests/stub_whois.$(OBJEXT) FadingCounter.$(OBJEXT) \
+	$(am__objects_13) wordlist.$(OBJEXT)
 nodist_tests_testHttpRequest_OBJECTS = $(am__objects_17)
 tests_testHttpRequest_OBJECTS = $(am_tests_testHttpRequest_OBJECTS) \
 	$(nodist_tests_testHttpRequest_OBJECTS)
@@ -1391,14 +1394,14 @@
 	tests/stub_neighbors.cc tests/stub_Port.cc tests/stub_pconn.cc \
 	tests/stub_store_client.cc store_rebuild.h \
 	tests/stub_store_rebuild.cc tests/stub_store_stats.cc tools.h \
-	tests/stub_tools.cc time.cc url.cc wordlist.h wordlist.cc \
-	CommonPool.h CompositePoolNode.h delay_pools.cc DelayId.cc \
-	DelayId.h DelayIdComposite.h DelayBucket.cc DelayBucket.h \
-	DelayConfig.cc DelayConfig.h DelayPool.cc DelayPool.h \
-	DelayPools.h DelaySpec.cc DelaySpec.h DelayTagged.cc \
-	DelayTagged.h DelayUser.cc DelayUser.h DelayVector.cc \
-	DelayVector.h NullDelayId.h ClientDelayConfig.cc \
-	ClientDelayConfig.h unlinkd.h unlinkd.cc
+	tests/stub_tools.cc time.cc tests/stub_libanyp.cc wordlist.h \
+	wordlist.cc CommonPool.h CompositePoolNode.h delay_pools.cc \
+	DelayId.cc DelayId.h DelayIdComposite.h DelayBucket.cc \
+	DelayBucket.h DelayConfig.cc DelayConfig.h DelayPool.cc \
+	DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \
+	DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \
+	DelayVector.cc DelayVector.h NullDelayId.h \
+	ClientDelayConfig.cc ClientDelayConfig.h unlinkd.h unlinkd.cc
 am_tests_testRock_OBJECTS = AccessLogEntry.$(OBJEXT) cbdata.$(OBJEXT) \
 	CollapsedForwarding.$(OBJEXT) tests/stub_CacheDigest.$(OBJEXT) \
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) fs_io.$(OBJEXT) \
@@ -1439,7 +1442,7 @@
 	tests/stub_pconn.$(OBJEXT) tests/stub_store_client.$(OBJEXT) \
 	tests/stub_store_rebuild.$(OBJEXT) \
 	tests/stub_store_stats.$(OBJEXT) tests/stub_tools.$(OBJEXT) \
-	time.$(OBJEXT) url.$(OBJEXT) wordlist.$(OBJEXT) \
+	time.$(OBJEXT) tests/stub_libanyp.$(OBJEXT) wordlist.$(OBJEXT) \
 	$(am__objects_3) $(am__objects_12)
 nodist_tests_testRock_OBJECTS = swap_log_op.$(OBJEXT) \
 	SquidMath.$(OBJEXT) $(am__objects_18)
@@ -1547,7 +1550,7 @@
 	tests/testStoreHashIndex.cc tests/testStoreHashIndex.h \
 	tests/testStoreSupport.cc tests/testStoreSupport.h \
 	tests/TestSwapDir.cc tests/TestSwapDir.h tests/stub_time.cc \
-	url.cc wordlist.h wordlist.cc
+	tests/stub_libanyp.cc wordlist.h wordlist.cc
 am_tests_testStore_OBJECTS = tests/stub_CacheDigest.$(OBJEXT) \
 	cbdata.$(OBJEXT) tests/stub_CollapsedForwarding.$(OBJEXT) \
 	ConfigOption.$(OBJEXT) ConfigParser.$(OBJEXT) $(am__objects_3) \
@@ -1593,7 +1596,8 @@
 	tests/testStoreController.$(OBJEXT) \
 	tests/testStoreHashIndex.$(OBJEXT) \
 	tests/testStoreSupport.$(OBJEXT) tests/TestSwapDir.$(OBJEXT) \
-	tests/stub_time.$(OBJEXT) url.$(OBJEXT) wordlist.$(OBJEXT)
+	tests/stub_time.$(OBJEXT) tests/stub_libanyp.$(OBJEXT) \
+	wordlist.$(OBJEXT)
 nodist_tests_testStore_OBJECTS = $(am__objects_18) SquidMath.$(OBJEXT) \
 	swap_log_op.$(OBJEXT)
 tests_testStore_OBJECTS = $(am_tests_testStore_OBJECTS) \
@@ -1706,9 +1710,9 @@
 	tests/stub_store_stats.cc tests/testURL.cc tests/testURL.h \
 	tests/testUriScheme.cc tests/testUriScheme.h \
 	tests/stub_time.cc tests/stub_EventLoop.cc tools.h tools.cc \
-	tests/stub_tunnel.cc url.cc urn.h urn.cc wccp2.h \
-	tests/stub_wccp2.cc whois.h tests/stub_whois.cc \
-	FadingCounter.cc win32.cc wordlist.h wordlist.cc
+	tests/stub_tunnel.cc urn.h urn.cc wccp2.h tests/stub_wccp2.cc \
+	whois.h tests/stub_whois.cc FadingCounter.cc win32.cc \
+	wordlist.h wordlist.cc
 am_tests_testURL_OBJECTS = AccessLogEntry.$(OBJEXT) BodyPipe.$(OBJEXT) \
 	cache_cf.$(OBJEXT) tests/stub_cache_manager.$(OBJEXT) \
 	tests/stub_CacheDigest.$(OBJEXT) CachePeer.$(OBJEXT) \
@@ -1762,7 +1766,7 @@
 	tests/stub_store_stats.$(OBJEXT) tests/testURL.$(OBJEXT) \
 	tests/testUriScheme.$(OBJEXT) tests/stub_time.$(OBJEXT) \
 	tests/stub_EventLoop.$(OBJEXT) tools.$(OBJEXT) \
-	tests/stub_tunnel.$(OBJEXT) url.$(OBJEXT) urn.$(OBJEXT) \
+	tests/stub_tunnel.$(OBJEXT) urn.$(OBJEXT) \
 	tests/stub_wccp2.$(OBJEXT) tests/stub_whois.$(OBJEXT) \
 	FadingCounter.$(OBJEXT) $(am__objects_13) wordlist.$(OBJEXT)
 nodist_tests_testURL_OBJECTS = $(am__objects_17)
@@ -1829,10 +1833,11 @@
 	HttpHeaderTools.cc HttpHeader.h HttpHeader.cc ClientInfo.h \
 	MemBuf.cc HttpHdrContRange.cc HttpHeaderFieldStat.h \
 	HttpHdrCc.h HttpHdrCc.cc HttpHdrCc.cci HttpHdrSc.cc \
-	HttpHdrScTarget.cc url.cc StatCounters.h StatCounters.cc \
-	StatHist.h StatHist.cc StrList.h StrList.cc HttpHdrRange.cc \
-	ETag.cc tests/stub_errorpage.cc tests/stub_HttpRequest.cc \
-	log/access_log.h tests/stub_access_log.cc refresh.h refresh.cc \
+	HttpHdrScTarget.cc tests/stub_libanyp.cc StatCounters.h \
+	StatCounters.cc StatHist.h StatHist.cc StrList.h StrList.cc \
+	HttpHdrRange.cc ETag.cc tests/stub_errorpage.cc \
+	tests/stub_HttpRequest.cc log/access_log.h \
+	tests/stub_access_log.cc refresh.h refresh.cc \
 	tests/stub_store_client.cc tools.h tests/stub_tools.cc \
 	tests/testStoreSupport.cc tests/testStoreSupport.h time.cc \
 	wordlist.h wordlist.cc
@@ -1874,9 +1879,10 @@
 	HttpHeaderTools.$(OBJEXT) HttpHeader.$(OBJEXT) \
 	MemBuf.$(OBJEXT) HttpHdrContRange.$(OBJEXT) \
 	HttpHdrCc.$(OBJEXT) HttpHdrSc.$(OBJEXT) \
-	HttpHdrScTarget.$(OBJEXT) url.$(OBJEXT) StatCounters.$(OBJEXT) \
-	StatHist.$(OBJEXT) StrList.$(OBJEXT) HttpHdrRange.$(OBJEXT) \
-	ETag.$(OBJEXT) tests/stub_errorpage.$(OBJEXT) \
+	HttpHdrScTarget.$(OBJEXT) tests/stub_libanyp.$(OBJEXT) \
+	StatCounters.$(OBJEXT) StatHist.$(OBJEXT) StrList.$(OBJEXT) \
+	HttpHdrRange.$(OBJEXT) ETag.$(OBJEXT) \
+	tests/stub_errorpage.$(OBJEXT) \
 	tests/stub_HttpRequest.$(OBJEXT) \
 	tests/stub_access_log.$(OBJEXT) refresh.$(OBJEXT) \
 	tests/stub_store_client.$(OBJEXT) tests/stub_tools.$(OBJEXT) \
@@ -1957,9 +1963,9 @@
 	tests/stub_libsecurity.cc tests/stub_main_cc.cc \
 	tests/stub_MemStore.cc tests/stub_store_stats.cc \
 	tests/stub_EventLoop.cc time.cc tools.h tools.cc \
-	tests/stub_tunnel.cc unlinkd.h unlinkd.cc url.cc urn.h urn.cc \
-	wccp2.h tests/stub_wccp2.cc whois.h tests/stub_whois.cc \
-	win32.cc wordlist.h wordlist.cc
+	tests/stub_tunnel.cc unlinkd.h unlinkd.cc \
+	tests/stub_libanyp.cc urn.h urn.cc wccp2.h tests/stub_wccp2.cc \
+	whois.h tests/stub_whois.cc win32.cc wordlist.h wordlist.cc
 am_tests_test_http_range_OBJECTS = AccessLogEntry.$(OBJEXT) \
 	BodyPipe.$(OBJEXT) cache_cf.$(OBJEXT) CachePeer.$(OBJEXT) \
 	cache_manager.$(OBJEXT) tests/stub_CacheDigest.$(OBJEXT) \
@@ -2012,10 +2018,10 @@
 	tests/stub_libsecurity.$(OBJEXT) tests/stub_main_cc.$(OBJEXT) \
 	tests/stub_MemStore.$(OBJEXT) tests/stub_store_stats.$(OBJEXT) \
 	tests/stub_EventLoop.$(OBJEXT) time.$(OBJEXT) tools.$(OBJEXT) \
-	tests/stub_tunnel.$(OBJEXT) $(am__objects_12) url.$(OBJEXT) \
-	urn.$(OBJEXT) tests/stub_wccp2.$(OBJEXT) \
-	tests/stub_whois.$(OBJEXT) $(am__objects_13) \
-	wordlist.$(OBJEXT)
+	tests/stub_tunnel.$(OBJEXT) $(am__objects_12) \
+	tests/stub_libanyp.$(OBJEXT) urn.$(OBJEXT) \
+	tests/stub_wccp2.$(OBJEXT) tests/stub_whois.$(OBJEXT) \
+	$(am__objects_13) wordlist.$(OBJEXT)
 nodist_tests_test_http_range_OBJECTS = $(am__objects_17)
 tests_test_http_range_OBJECTS = $(am_tests_test_http_range_OBJECTS) \
 	$(nodist_tests_test_http_range_OBJECTS)
@@ -2906,9 +2912,9 @@
 	StoreSearch.h StoreStats.cc StoreStats.h StoreSwapLogData.cc \
 	StoreSwapLogData.h swap_log_op.h Transients.cc Transients.h \
 	MemStore.cc MemStore.h time.cc TimeOrTag.h tools.h tools.cc \
-	tunnel.cc typedefs.h $(UNLINKDSOURCE) url.cc URL.h urn.h \
-	urn.cc wccp.h wccp.cc wccp2.h wccp2.cc whois.h whois.cc \
-	wordlist.h wordlist.cc XactionInitiator.h XactionInitiator.cc \
+	tunnel.cc typedefs.h $(UNLINKDSOURCE) urn.h urn.cc wccp.h \
+	wccp.cc wccp2.h wccp2.cc whois.h whois.cc wordlist.h \
+	wordlist.cc XactionInitiator.h XactionInitiator.cc \
 	$(WIN32_SOURCE) $(WINSVC_SOURCE) $(am__append_9)
 EXTRA_squid_SOURCES = \
 	$(all_AUTHMODULES) \
@@ -3103,6 +3109,7 @@
 	tests/stub_ipc.cc \
 	tests/stub_ipc_Forwarder.cc \
 	tests/stub_ipc_TypedMsgHdr.cc \
+	tests/stub_libanyp.cc \
 	tests/stub_libauth_acls.cc \
 	tests/stub_libauth.cc \
 	tests/stub_libcomm.cc \
@@ -3262,7 +3269,7 @@
 	tests/testHttpReply.cc \
 	tests/testHttpReply.h \
 	tests/stub_time.cc \
-	url.cc \
+	tests/stub_libanyp.cc \
 	wordlist.h \
 	wordlist.cc
 
@@ -3387,8 +3394,7 @@
 	tests/testACLMaxUserIP.cc \
 	tests/testACLMaxUserIP.h \
 	tests/stub_time.cc \
-	url.cc \
-	URL.h \
+	tests/stub_libanyp.cc \
 	MemBuf.cc \
 	wordlist.h \
 	wordlist.cc
@@ -3642,7 +3648,7 @@
 	tests/stub_SwapDir.cc \
 	MemStore.cc \
 	$(UNLINKDSOURCE) \
-	url.cc \
+	tests/stub_libanyp.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -3828,7 +3834,7 @@
 	tests/testStoreSupport.h \
 	tests/stub_time.cc \
 	$(UNLINKDSOURCE) \
-	url.cc \
+	tests/stub_libanyp.cc \
 	$(WIN32_SOURCE) \
 	wordlist.h \
 	wordlist.cc \
@@ -4083,7 +4089,7 @@
 	tests/stub_tunnel.cc \
 	MemStore.cc \
 	$(UNLINKDSOURCE) \
-	url.cc \
+	tests/stub_libanyp.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -4320,7 +4326,7 @@
 	tests/stub_tunnel.cc \
 	MemStore.cc \
 	$(UNLINKDSOURCE) \
-	url.cc \
+	tests/stub_libanyp.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -4553,7 +4559,7 @@
 	tools.cc \
 	tests/stub_tunnel.cc \
 	$(UNLINKDSOURCE) \
-	url.cc \
+	tests/stub_libanyp.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -4661,6 +4667,7 @@
 	tests/testHttp1Parser.cc \
 	tests/testHttp1Parser.h \
 	tests/stub_time.cc \
+	tests/stub_libanyp.cc \
 	wordlist.h \
 	wordlist.cc
 
@@ -4860,7 +4867,6 @@
 	tests/stub_tunnel.cc \
 	tests/stub_SwapDir.cc \
 	MemStore.cc \
-	url.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -5103,7 +5109,7 @@
 	tests/TestSwapDir.cc \
 	tests/TestSwapDir.h \
 	tests/stub_time.cc \
-	url.cc \
+	tests/stub_libanyp.cc \
 	wordlist.h \
 	wordlist.cc
 
@@ -5301,7 +5307,7 @@
 	HttpHdrCc.cci \
 	HttpHdrSc.cc \
 	HttpHdrScTarget.cc \
-	url.cc \
+	tests/stub_libanyp.cc \
 	StatCounters.h \
 	StatCounters.cc \
 	StatHist.h \
@@ -5503,7 +5509,7 @@
 	tools.h \
 	tests/stub_tools.cc \
 	time.cc \
-	url.cc \
+	tests/stub_libanyp.cc \
 	wordlist.h \
 	wordlist.cc \
 	$(DELAY_POOL_SOURCE) \
@@ -5731,7 +5737,6 @@
 	tools.h \
 	tools.cc \
 	tests/stub_tunnel.cc \
-	url.cc \
 	urn.h \
 	urn.cc \
 	wccp2.h \
@@ -6275,6 +6280,8 @@
 	tests/$(DEPDIR)/$(am__dirstamp)
 tests/stub_time.$(OBJEXT): tests/$(am__dirstamp) \
 	tests/$(DEPDIR)/$(am__dirstamp)
+tests/stub_libanyp.$(OBJEXT): tests/$(am__dirstamp) \
+	tests/$(DEPDIR)/$(am__dirstamp)
 
 tests/testACLMaxUserIP$(EXEEXT): $(tests_testACLMaxUserIP_OBJECTS) $(tests_testACLMaxUserIP_DEPENDENCIES) $(EXTRA_tests_testACLMaxUserIP_DEPENDENCIES) tests/$(am__dirstamp)
 	@rm -f tests/testACLMaxUserIP$(EXEEXT)
@@ -6701,7 +6708,6 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ufsdump.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unlinkd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unlinkd_daemon.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/url.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/urn.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wccp.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wccp2.Po@am__quote@
@@ -6753,6 +6759,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_ipc_Forwarder.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_ipc_TypedMsgHdr.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_ipcache.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libanyp.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libauth.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libauth_acls.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/stub_libcomm.Po@am__quote@
diff -u -r -N squid-4.0.25/src/MemStore.cc squid-4.1/src/MemStore.cc
--- squid-4.0.25/src/MemStore.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/MemStore.cc	2018-07-02 15:26:07.000000000 +1200
@@ -556,7 +556,6 @@
         const int result = rep->httpMsgParseStep(mb.buf, buf.length, eof);
         if (result > 0) {
             assert(rep->pstate == psParsed);
-            EBIT_CLR(e.flags, ENTRY_FWD_HDR_WAIT);
         } else if (result < 0) {
             debugs(20, DBG_IMPORTANT, "Corrupted mem-cached headers: " << e);
             return false;
@@ -657,15 +656,9 @@
 void
 MemStore::copyToShm(StoreEntry &e)
 {
-    // prevents remote readers from getting ENTRY_FWD_HDR_WAIT entries and
-    // not knowing when the wait is over
-    if (EBIT_TEST(e.flags, ENTRY_FWD_HDR_WAIT)) {
-        debugs(20, 5, "postponing copying " << e << " for ENTRY_FWD_HDR_WAIT");
-        return;
-    }
-
     assert(map);
     assert(e.mem_obj);
+    Must(!EBIT_TEST(e.flags, ENTRY_FWD_HDR_WAIT));
 
     const int64_t eSize = e.mem_obj->endOffset();
     if (e.mem_obj->memCache.offset >= eSize) {
diff -u -r -N squid-4.0.25/src/mgr/Forwarder.cc squid-4.1/src/mgr/Forwarder.cc
--- squid-4.0.25/src/mgr/Forwarder.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/mgr/Forwarder.cc	2018-07-02 15:26:07.000000000 +1200
@@ -37,7 +37,6 @@
 
     HTTPMSGLOCK(httpRequest);
     entry->lock("Mgr::Forwarder");
-    EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT);
 
     closer = asyncCall(16, 5, "Mgr::Forwarder::noteCommClosed",
                        CommCbMemFunT<Forwarder, CommCloseCbParams>(this, &Forwarder::noteCommClosed));
@@ -110,7 +109,6 @@
     Must(entry != NULL);
     Must(httpRequest != NULL);
 
-    EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
     entry->buffer();
     entry->replaceHttpReply(error->BuildHttpReply());
     entry->expires = squid_curtime;
diff -u -r -N squid-4.0.25/src/neighbors.cc squid-4.1/src/neighbors.cc
--- squid-4.0.25/src/neighbors.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/neighbors.cc	2018-07-02 15:26:07.000000000 +1200
@@ -44,7 +44,6 @@
 #include "Store.h"
 #include "store_key_md5.h"
 #include "tools.h"
-#include "URL.h"
 
 /* count mcast group peers every 15 minutes */
 #define MCAST_COUNT_RATE 900
@@ -111,7 +110,7 @@
 }
 
 peer_t
-neighborType(const CachePeer * p, const URL &url)
+neighborType(const CachePeer * p, const AnyP::Uri &url)
 {
 
     const NeighborTypeDomainList *d = NULL;
@@ -1374,7 +1373,7 @@
     MemObject *mem;
     icp_common_t *query;
     int reqnum;
-    // TODO: use class URL instead of constructing and re-parsing a string
+    // TODO: use class AnyP::Uri instead of constructing and re-parsing a string
     LOCAL_ARRAY(char, url, MAX_URL);
     assert(p->type == PEER_MULTICAST);
     p->mcast.flags.count_event_pending = false;
diff -u -r -N squid-4.0.25/src/neighbors.h squid-4.1/src/neighbors.h
--- squid-4.0.25/src/neighbors.h	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/neighbors.h	2018-07-02 15:26:07.000000000 +1200
@@ -11,6 +11,7 @@
 #ifndef SQUID_NEIGHBORS_H_
 #define SQUID_NEIGHBORS_H_
 
+#include "anyp/forward.h"
 #include "enums.h"
 #include "ICP.h"
 #include "lookup_t.h"
@@ -20,7 +21,6 @@
 class HttpRequestMethod;
 class CachePeer;
 class StoreEntry;
-class URL;
 
 CachePeer *getFirstPeer(void);
 CachePeer *getFirstUpParent(HttpRequest *);
@@ -54,7 +54,7 @@
 void peerNoteDigestGone(CachePeer * p);
 int neighborUp(const CachePeer * e);
 const char *neighborTypeStr(const CachePeer * e);
-peer_t neighborType(const CachePeer *, const URL &);
+peer_t neighborType(const CachePeer *, const AnyP::Uri &);
 void peerConnectFailed(CachePeer *);
 void peerConnectSucceded(CachePeer *);
 void dump_peer_options(StoreEntry *, CachePeer *);
diff -u -r -N squid-4.0.25/src/peer_select.cc squid-4.1/src/peer_select.cc
--- squid-4.0.25/src/peer_select.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/peer_select.cc	2018-07-02 15:26:07.000000000 +1200
@@ -33,7 +33,6 @@
 #include "SquidConfig.h"
 #include "SquidTime.h"
 #include "Store.h"
-#include "URL.h"
 
 static struct {
     int timeouts;
diff -u -r -N squid-4.0.25/src/refresh.cc squid-4.1/src/refresh.cc
--- squid-4.0.25/src/refresh.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/refresh.cc	2018-07-02 15:26:07.000000000 +1200
@@ -22,7 +22,6 @@
 #include "SquidConfig.h"
 #include "SquidTime.h"
 #include "Store.h"
-#include "URL.h"
 #include "util.h"
 
 typedef enum {
diff -u -r -N squid-4.0.25/src/security/cert_validators/fake/security_fake_certverify.8 squid-4.1/src/security/cert_validators/fake/security_fake_certverify.8
--- squid-4.0.25/src/security/cert_validators/fake/security_fake_certverify.8	2018-06-12 04:56:21.000000000 +1200
+++ squid-4.1/src/security/cert_validators/fake/security_fake_certverify.8	2018-07-02 15:39:08.000000000 +1200
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "SECURITY_FAKE_CERTVERIFY 8"
-.TH SECURITY_FAKE_CERTVERIFY 8 "2018-06-11" "perl v5.26.2" "User Contributed Perl Documentation"
+.TH SECURITY_FAKE_CERTVERIFY 8 "2018-07-02" "perl v5.26.2" "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-4.0.25/src/servers/FtpServer.cc squid-4.1/src/servers/FtpServer.cc
--- squid-4.0.25/src/servers/FtpServer.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/servers/FtpServer.cc	2018-07-02 15:26:07.000000000 +1200
@@ -339,7 +339,7 @@
 void
 Ftp::Server::calcUri(const SBuf *file)
 {
-    // TODO: fill a class URL instead of string
+    // TODO: fill a class AnyP::Uri instead of string
     uri = "ftp://";
     uri.append(host);
     if (port->ftp_track_dirs && master->workingDir.length()) {
@@ -1545,6 +1545,8 @@
         ClientHttpRequest *http = pipeline.front()->http;
         HttpRequest *request = http->request;
         ACLFilledChecklist bodyContinuationCheck(Config.accessList.forceRequestBodyContinuation, request, NULL);
+        bodyContinuationCheck.al = http->al;
+        bodyContinuationCheck.syncAle(request, http->log_uri);
         if (bodyContinuationCheck.fastCheck().allowed()) {
             request->forcedBodyContinuation = true;
             if (checkDataConnPost()) {
diff -u -r -N squid-4.0.25/src/servers/Http1Server.cc squid-4.1/src/servers/Http1Server.cc
--- squid-4.0.25/src/servers/Http1Server.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/servers/Http1Server.cc	2018-07-02 15:26:07.000000000 +1200
@@ -249,6 +249,8 @@
 
         if (Config.accessList.forceRequestBodyContinuation) {
             ACLFilledChecklist bodyContinuationCheck(Config.accessList.forceRequestBodyContinuation, request.getRaw(), NULL);
+            bodyContinuationCheck.al = http->al;
+            bodyContinuationCheck.syncAle(request.getRaw(), http->log_uri);
             if (bodyContinuationCheck.fastCheck().allowed()) {
                 debugs(33, 5, "Body Continuation forced");
                 request->forcedBodyContinuation = true;
diff -u -r -N squid-4.0.25/src/ssl/ServerBump.cc squid-4.1/src/ssl/ServerBump.cc
--- squid-4.0.25/src/ssl/ServerBump.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/ssl/ServerBump.cc	2018-07-02 15:26:07.000000000 +1200
@@ -9,14 +9,13 @@
 /* DEBUG: section 33    Client-side Routines */
 
 #include "squid.h"
-
+#include "anyp/Uri.h"
 #include "client_side.h"
 #include "FwdState.h"
 #include "http/Stream.h"
 #include "ssl/ServerBump.h"
 #include "Store.h"
 #include "StoreClient.h"
-#include "URL.h"
 
 CBDATA_NAMESPACED_CLASS_INIT(Ssl, ServerBump);
 
diff -u -r -N squid-4.0.25/src/ssl/support.cc squid-4.1/src/ssl/support.cc
--- squid-4.0.25/src/ssl/support.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/ssl/support.cc	2018-07-02 15:26:07.000000000 +1200
@@ -17,6 +17,7 @@
 
 #include "acl/FilledChecklist.h"
 #include "anyp/PortCfg.h"
+#include "anyp/Uri.h"
 #include "fatal.h"
 #include "fd.h"
 #include "fde.h"
@@ -31,7 +32,6 @@
 #include "ssl/ErrorDetail.h"
 #include "ssl/gadgets.h"
 #include "ssl/support.h"
-#include "URL.h"
 
 #include <cerrno>
 
diff -u -r -N squid-4.0.25/src/store/id_rewriters/file/storeid_file_rewrite.8 squid-4.1/src/store/id_rewriters/file/storeid_file_rewrite.8
--- squid-4.0.25/src/store/id_rewriters/file/storeid_file_rewrite.8	2018-06-12 04:56:19.000000000 +1200
+++ squid-4.1/src/store/id_rewriters/file/storeid_file_rewrite.8	2018-07-02 15:39:07.000000000 +1200
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "STOREID_FILE_REWRITE 8"
-.TH STOREID_FILE_REWRITE 8 "2018-06-11" "perl v5.26.2" "User Contributed Perl Documentation"
+.TH STOREID_FILE_REWRITE 8 "2018-07-02" "perl v5.26.2" "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-4.0.25/src/store.cc squid-4.1/src/store.cc
--- squid-4.0.25/src/store.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/store.cc	2018-07-02 15:26:07.000000000 +1200
@@ -828,8 +828,12 @@
     storeGetMemSpace(writeBuffer.length);
     mem_obj->write(writeBuffer);
 
-    if (!EBIT_TEST(flags, DELAY_SENDING))
-        invokeHandlers();
+    if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT) && !mem_obj->readAheadPolicyCanRead()) {
+        debugs(20, 3, "allow Store clients to get entry content after buffering too much for " << *this);
+        EBIT_CLR(flags, ENTRY_FWD_HDR_WAIT);
+    }
+
+    invokeHandlers();
 }
 
 /* Append incoming data from a primary server to an entry. */
@@ -1073,6 +1077,9 @@
 {
     debugs(20, 3, "storeComplete: '" << getMD5Text() << "'");
 
+    // To preserve forwarding retries, call FwdState::complete() instead.
+    EBIT_CLR(flags, ENTRY_FWD_HDR_WAIT);
+
     if (store_status != STORE_PENDING) {
         /*
          * if we're not STORE_PENDING, then probably we got aborted
@@ -1129,6 +1136,9 @@
 
     EBIT_SET(flags, ENTRY_ABORTED);
 
+    // allow the Store clients to be told about the problem
+    EBIT_CLR(flags, ENTRY_FWD_HDR_WAIT);
+
     setMemStatus(NOT_IN_MEMORY);
 
     store_status = STORE_OK;
@@ -1823,7 +1833,6 @@
     buffer();
     rep->packHeadersInto(this);
     mem_obj->markEndOfReplyHeaders();
-    EBIT_CLR(flags, ENTRY_FWD_HDR_WAIT);
 
     rep->body.packInto(this);
     flush();
diff -u -r -N squid-4.0.25/src/store_client.cc squid-4.1/src/store_client.cc
--- squid-4.0.25/src/store_client.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/store_client.cc	2018-07-02 15:26:07.000000000 +1200
@@ -279,11 +279,6 @@
         return;
     }
 
-    if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) {
-        debugs(90, 5, "storeClientCopy2: returning because ENTRY_FWD_HDR_WAIT set");
-        return;
-    }
-
     if (sc->flags.store_copying) {
         sc->flags.copy_event_pending = true;
         debugs(90, 3, "storeClientCopy2: Queueing storeClientCopyEvent()");
@@ -711,6 +706,15 @@
 void
 StoreEntry::invokeHandlers()
 {
+    if (EBIT_TEST(flags, DELAY_SENDING)) {
+        debugs(90, 3, "DELAY_SENDING is on, exiting " << *this);
+        return;
+    }
+    if (EBIT_TEST(flags, ENTRY_FWD_HDR_WAIT)) {
+        debugs(90, 3, "ENTRY_FWD_HDR_WAIT is on, exiting " << *this);
+        return;
+    }
+
     /* Commit what we can to disk, if appropriate */
     swapOut();
     int i = 0;
diff -u -r -N squid-4.0.25/src/store_key_md5.cc squid-4.1/src/store_key_md5.cc
--- squid-4.0.25/src/store_key_md5.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/store_key_md5.cc	2018-07-02 15:26:07.000000000 +1200
@@ -12,7 +12,6 @@
 #include "HttpRequest.h"
 #include "md5.h"
 #include "store_key_md5.h"
-#include "URL.h"
 
 static cache_key null_key[SQUID_MD5_DIGEST_LENGTH];
 
diff -u -r -N squid-4.0.25/src/tests/stub_libanyp.cc squid-4.1/src/tests/stub_libanyp.cc
--- squid-4.0.25/src/tests/stub_libanyp.cc	1970-01-01 12:00:00.000000000 +1200
+++ squid-4.1/src/tests/stub_libanyp.cc	2018-07-02 15:26:07.000000000 +1200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+
+#define STUB_API "anyp/libanyp.la"
+#include "tests/STUB.h"
+
+#include "anyp/Uri.h"
+AnyP::Uri::Uri(AnyP::UriScheme const &) {STUB}
+void AnyP::Uri::touch() STUB
+bool AnyP::Uri::parse(const HttpRequestMethod&, const char *) STUB_RETVAL(true)
+void AnyP::Uri::host(const char *) STUB
+static SBuf nil;
+const SBuf &AnyP::Uri::path() const STUB_RETVAL(nil)
+const SBuf &AnyP::Uri::SlashPath()
+{
+    static SBuf slash("/");
+    return slash;
+}
+const SBuf &AnyP::Uri::Asterisk()
+{
+    static SBuf asterisk("*");
+    return asterisk;
+}
+SBuf &AnyP::Uri::authority(bool) const STUB_RETVAL(nil)
+SBuf &AnyP::Uri::absolute() const STUB_RETVAL(nil)
+void urlInitialize() STUB
+char *urlCanonicalClean(const HttpRequest *) STUB_RETVAL(nullptr)
+const char *urlCanonicalFakeHttps(const HttpRequest *) STUB_RETVAL(nullptr)
+bool urlIsRelative(const char *) STUB_RETVAL(false)
+char *urlMakeAbsolute(const HttpRequest *, const char *)STUB_RETVAL(nullptr)
+char *urlRInternal(const char *, unsigned short, const char *, const char *) STUB_RETVAL(nullptr)
+char *urlInternal(const char *, const char *) STUB_RETVAL(nullptr)
+int matchDomainName(const char *, const char *, uint) STUB_RETVAL(0)
+int urlCheckRequest(const HttpRequest *) STUB_RETVAL(0)
+char *urlHostname(const char *) STUB_RETVAL(nullptr)
+void urlExtMethodConfigure() STUB
+
diff -u -r -N squid-4.0.25/src/tests/stub_libicmp.cc squid-4.1/src/tests/stub_libicmp.cc
--- squid-4.0.25/src/tests/stub_libicmp.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/tests/stub_libicmp.cc	2018-07-02 15:26:07.000000000 +1200
@@ -30,7 +30,7 @@
 void netdbFreeMemory(void) STUB
 int netdbHostHops(const char *host) STUB_RETVAL(-1)
 int netdbHostRtt(const char *host) STUB_RETVAL(-1)
-void netdbUpdatePeer(const URL &, CachePeer * e, int rtt, int hops) STUB
+void netdbUpdatePeer(const AnyP::Uri &, CachePeer *, int, int) STUB
 void netdbDeleteAddrNetwork(Ip::Address &addr) STUB
 void netdbBinaryExchange(StoreEntry *) STUB
 void netdbExchangeStart(void *) STUB
diff -u -r -N squid-4.0.25/src/tests/Stub.list squid-4.1/src/tests/Stub.list
--- squid-4.0.25/src/tests/Stub.list	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/tests/Stub.list	2018-07-02 15:26:07.000000000 +1200
@@ -41,6 +41,7 @@
 	tests/stub_ipc.cc \
 	tests/stub_ipc_Forwarder.cc \
 	tests/stub_ipc_TypedMsgHdr.cc \
+	tests/stub_libanyp.cc \
 	tests/stub_libauth_acls.cc \
 	tests/stub_libauth.cc \
 	tests/stub_libcomm.cc \
diff -u -r -N squid-4.0.25/src/tests/testURL.cc squid-4.1/src/tests/testURL.cc
--- squid-4.0.25/src/tests/testURL.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/tests/testURL.cc	2018-07-02 15:26:07.000000000 +1200
@@ -10,10 +10,10 @@
 
 #include <cppunit/TestAssert.h>
 
+#include "anyp/Uri.h"
 #include "Debug.h"
-#include "testURL.h"
+#include "tests/testURL.h"
 #include "unitTestMain.h"
-#include "URL.h"
 
 #include <sstream>
 
@@ -36,11 +36,11 @@
 testURL::testConstructScheme()
 {
     AnyP::UriScheme empty_scheme;
-    URL protoless_url(AnyP::PROTO_NONE);
+    AnyP::Uri protoless_url(AnyP::PROTO_NONE);
     CPPUNIT_ASSERT_EQUAL(empty_scheme, protoless_url.getScheme());
 
     AnyP::UriScheme ftp_scheme(AnyP::PROTO_FTP);
-    URL ftp_url(AnyP::PROTO_FTP);
+    AnyP::Uri ftp_url(AnyP::PROTO_FTP);
     CPPUNIT_ASSERT_EQUAL(ftp_scheme, ftp_url.getScheme());
 }
 
@@ -53,10 +53,10 @@
 testURL::testDefaultConstructor()
 {
     AnyP::UriScheme aScheme;
-    URL aUrl;
+    AnyP::Uri aUrl;
     CPPUNIT_ASSERT_EQUAL(aScheme, aUrl.getScheme());
 
-    URL *urlPointer = new URL;
+    auto *urlPointer = new AnyP::Uri;
     CPPUNIT_ASSERT(urlPointer != NULL);
     delete urlPointer;
 }
diff -u -r -N squid-4.0.25/src/url.cc squid-4.1/src/url.cc
--- squid-4.0.25/src/url.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/url.cc	1970-01-01 12:00:00.000000000 +1200
@@ -1,938 +0,0 @@
-/*
- * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-/* DEBUG: section 23    URL Parsing */
-
-#include "squid.h"
-#include "globals.h"
-#include "HttpRequest.h"
-#include "rfc1738.h"
-#include "SquidConfig.h"
-#include "SquidString.h"
-#include "URL.h"
-
-static const char valid_hostname_chars_u[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-    "abcdefghijklmnopqrstuvwxyz"
-    "0123456789-._"
-    "[:]"
-    ;
-static const char valid_hostname_chars[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-    "abcdefghijklmnopqrstuvwxyz"
-    "0123456789-."
-    "[:]"
-    ;
-
-const SBuf &
-URL::Asterisk()
-{
-    static SBuf star("*");
-    return star;
-}
-
-const SBuf &
-URL::SlashPath()
-{
-    static SBuf slash("/");
-    return slash;
-}
-
-void
-URL::host(const char *src)
-{
-    hostAddr_.setEmpty();
-    hostAddr_ = src;
-    if (hostAddr_.isAnyAddr()) {
-        xstrncpy(host_, src, sizeof(host_));
-        hostIsNumeric_ = false;
-    } else {
-        hostAddr_.toHostStr(host_, sizeof(host_));
-        debugs(23, 3, "given IP: " << hostAddr_);
-        hostIsNumeric_ = 1;
-    }
-    touch();
-}
-
-const SBuf &
-URL::path() const
-{
-    // RFC 3986 section 3.3 says path can be empty (path-abempty).
-    // RFC 7230 sections 2.7.3, 5.3.1, 5.7.2 - says path cannot be empty, default to "/"
-    // at least when sending and using. We must still accept path-abempty as input.
-    if (path_.isEmpty() && (scheme_ == AnyP::PROTO_HTTP || scheme_ == AnyP::PROTO_HTTPS))
-        return SlashPath();
-
-    return path_;
-}
-
-void
-urlInitialize(void)
-{
-    debugs(23, 5, "urlInitialize: Initializing...");
-    /* this ensures that the number of protocol strings is the same as
-     * the enum slots allocated because the last enum is always 'MAX'.
-     */
-    assert(strcmp(AnyP::ProtocolType_str[AnyP::PROTO_MAX], "MAX") == 0);
-    /*
-     * These test that our matchDomainName() function works the
-     * way we expect it to.
-     */
-    assert(0 == matchDomainName("foo.com", "foo.com"));
-    assert(0 == matchDomainName(".foo.com", "foo.com"));
-    assert(0 == matchDomainName("foo.com", ".foo.com"));
-    assert(0 == matchDomainName(".foo.com", ".foo.com"));
-    assert(0 == matchDomainName("x.foo.com", ".foo.com"));
-    assert(0 == matchDomainName("y.x.foo.com", ".foo.com"));
-    assert(0 != matchDomainName("x.foo.com", "foo.com"));
-    assert(0 != matchDomainName("foo.com", "x.foo.com"));
-    assert(0 != matchDomainName("bar.com", "foo.com"));
-    assert(0 != matchDomainName(".bar.com", "foo.com"));
-    assert(0 != matchDomainName(".bar.com", ".foo.com"));
-    assert(0 != matchDomainName("bar.com", ".foo.com"));
-    assert(0 < matchDomainName("zzz.com", "foo.com"));
-    assert(0 > matchDomainName("aaa.com", "foo.com"));
-    assert(0 == matchDomainName("FOO.com", "foo.COM"));
-    assert(0 < matchDomainName("bfoo.com", "afoo.com"));
-    assert(0 > matchDomainName("afoo.com", "bfoo.com"));
-    assert(0 < matchDomainName("x-foo.com", ".foo.com"));
-
-    assert(0 == matchDomainName(".foo.com", ".foo.com", mdnRejectSubsubDomains));
-    assert(0 == matchDomainName("x.foo.com", ".foo.com", mdnRejectSubsubDomains));
-    assert(0 != matchDomainName("y.x.foo.com", ".foo.com", mdnRejectSubsubDomains));
-    assert(0 != matchDomainName(".x.foo.com", ".foo.com", mdnRejectSubsubDomains));
-
-    assert(0 == matchDomainName("*.foo.com", "x.foo.com", mdnHonorWildcards));
-    assert(0 == matchDomainName("*.foo.com", ".x.foo.com", mdnHonorWildcards));
-    assert(0 == matchDomainName("*.foo.com", ".foo.com", mdnHonorWildcards));
-    assert(0 != matchDomainName("*.foo.com", "foo.com", mdnHonorWildcards));
-
-    /* more cases? */
-}
-
-/**
- * Parse the scheme name from string b, into protocol type.
- * The string must be 0-terminated.
- */
-AnyP::ProtocolType
-urlParseProtocol(const char *b)
-{
-    // make e point to the ':' character
-    const char *e = b + strcspn(b, ":");
-    int len = e - b;
-
-    /* test common stuff first */
-
-    if (strncasecmp(b, "http", len) == 0)
-        return AnyP::PROTO_HTTP;
-
-    if (strncasecmp(b, "ftp", len) == 0)
-        return AnyP::PROTO_FTP;
-
-    if (strncasecmp(b, "https", len) == 0)
-        return AnyP::PROTO_HTTPS;
-
-    if (strncasecmp(b, "file", len) == 0)
-        return AnyP::PROTO_FTP;
-
-    if (strncasecmp(b, "coap", len) == 0)
-        return AnyP::PROTO_COAP;
-
-    if (strncasecmp(b, "coaps", len) == 0)
-        return AnyP::PROTO_COAPS;
-
-    if (strncasecmp(b, "gopher", len) == 0)
-        return AnyP::PROTO_GOPHER;
-
-    if (strncasecmp(b, "wais", len) == 0)
-        return AnyP::PROTO_WAIS;
-
-    if (strncasecmp(b, "cache_object", len) == 0)
-        return AnyP::PROTO_CACHE_OBJECT;
-
-    if (strncasecmp(b, "urn", len) == 0)
-        return AnyP::PROTO_URN;
-
-    if (strncasecmp(b, "whois", len) == 0)
-        return AnyP::PROTO_WHOIS;
-
-    if (len > 0)
-        return AnyP::PROTO_UNKNOWN;
-
-    return AnyP::PROTO_NONE;
-}
-
-/*
- * Parse a URI/URL.
- *
- * Stores parsed values in the `request` argument.
- *
- * This abuses HttpRequest as a way of representing the parsed url
- * and its components.
- * method is used to switch parsers and to init the HttpRequest.
- * If method is Http::METHOD_CONNECT, then rather than a URL a hostname:port is
- * looked for.
- * The url is non const so that if its too long we can NULL-terminate it in place.
- */
-
-/*
- * This routine parses a URL. Its assumed that the URL is complete -
- * ie, the end of the string is the end of the URL. Don't pass a partial
- * URL here as this routine doesn't have any way of knowing whether
- * its partial or not (ie, it handles the case of no trailing slash as
- * being "end of host with implied path of /".
- */
-bool
-URL::parse(const HttpRequestMethod& method, const char *url)
-{
-    LOCAL_ARRAY(char, proto, MAX_URL);
-    LOCAL_ARRAY(char, login, MAX_URL);
-    LOCAL_ARRAY(char, foundHost, MAX_URL);
-    LOCAL_ARRAY(char, urlpath, MAX_URL);
-    char *t = NULL;
-    char *q = NULL;
-    int foundPort;
-    AnyP::ProtocolType protocol = AnyP::PROTO_NONE;
-    int l;
-    int i;
-    const char *src;
-    char *dst;
-    proto[0] = foundHost[0] = urlpath[0] = login[0] = '\0';
-
-    if ((l = strlen(url)) + Config.appendDomainLen > (MAX_URL - 1)) {
-        debugs(23, DBG_IMPORTANT, MYNAME << "URL too large (" << l << " bytes)");
-        return false;
-    }
-    if (method == Http::METHOD_CONNECT) {
-        /*
-         * RFC 7230 section 5.3.3:  authority-form = authority
-         *  "excluding any userinfo and its "@" delimiter"
-         *
-         * RFC 3986 section 3.2:    authority = [ userinfo "@" ] host [ ":" port ]
-         *
-         * As an HTTP(S) proxy we assume HTTPS (443) if no port provided.
-         */
-        foundPort = 443;
-
-        if (sscanf(url, "[%[^]]]:%d", foundHost, &foundPort) < 1)
-            if (sscanf(url, "%[^:]:%d", foundHost, &foundPort) < 1)
-                return false;
-
-    } else if ((method == Http::METHOD_OPTIONS || method == Http::METHOD_TRACE) &&
-               URL::Asterisk().cmp(url) == 0) {
-        parseFinish(AnyP::PROTO_HTTP, nullptr, url, foundHost, SBuf(), 80 /* HTTP default port */);
-        return true;
-    } else if (strncmp(url, "urn:", 4) == 0) {
-        debugs(23, 3, "Split URI '" << url << "' into proto='urn', path='" << (url+4) << "'");
-        debugs(50, 5, "urn=" << (url+4));
-        setScheme(AnyP::PROTO_URN, nullptr);
-        path(url + 4);
-        return true;
-    } else {
-        /* Parse the URL: */
-        src = url;
-        i = 0;
-        /* Find first : - everything before is protocol */
-        for (i = 0, dst = proto; i < l && *src != ':'; ++i, ++src, ++dst) {
-            *dst = *src;
-        }
-        if (i >= l)
-            return false;
-        *dst = '\0';
-
-        /* Then its :// */
-        if ((i+3) > l || *src != ':' || *(src + 1) != '/' || *(src + 2) != '/')
-            return false;
-        i += 3;
-        src += 3;
-
-        /* Then everything until first /; thats host (and port; which we'll look for here later) */
-        // bug 1881: If we don't get a "/" then we imply it was there
-        // bug 3074: We could just be given a "?" or "#". These also imply "/"
-        // bug 3233: whitespace is also a hostname delimiter.
-        for (dst = foundHost; i < l && *src != '/' && *src != '?' && *src != '#' && *src != '\0' && !xisspace(*src); ++i, ++src, ++dst) {
-            *dst = *src;
-        }
-
-        /*
-         * We can't check for "i >= l" here because we could be at the end of the line
-         * and have a perfectly valid URL w/ no trailing '/'. In this case we assume we've
-         * been -given- a valid URL and the path is just '/'.
-         */
-        if (i > l)
-            return false;
-        *dst = '\0';
-
-        // bug 3074: received 'path' starting with '?', '#', or '\0' implies '/'
-        if (*src == '?' || *src == '#' || *src == '\0') {
-            urlpath[0] = '/';
-            dst = &urlpath[1];
-        } else {
-            dst = urlpath;
-        }
-        /* Then everything from / (inclusive) until \r\n or \0 - thats urlpath */
-        for (; i < l && *src != '\r' && *src != '\n' && *src != '\0'; ++i, ++src, ++dst) {
-            *dst = *src;
-        }
-
-        /* We -could- be at the end of the buffer here */
-        if (i > l)
-            return false;
-        /* If the URL path is empty we set it to be "/" */
-        if (dst == urlpath) {
-            *dst = '/';
-            ++dst;
-        }
-        *dst = '\0';
-
-        protocol = urlParseProtocol(proto);
-        foundPort = AnyP::UriScheme(protocol).defaultPort();
-
-        /* Is there any login information? (we should eventually parse it above) */
-        t = strrchr(foundHost, '@');
-        if (t != NULL) {
-            strncpy((char *) login, (char *) foundHost, sizeof(login)-1);
-            login[sizeof(login)-1] = '\0';
-            t = strrchr(login, '@');
-            *t = 0;
-            strncpy((char *) foundHost, t + 1, sizeof(foundHost)-1);
-            foundHost[sizeof(foundHost)-1] = '\0';
-            // Bug 4498: URL-unescape the login info after extraction
-            rfc1738_unescape(login);
-        }
-
-        /* Is there any host information? (we should eventually parse it above) */
-        if (*foundHost == '[') {
-            /* strip any IPA brackets. valid under IPv6. */
-            dst = foundHost;
-            /* only for IPv6 sadly, pre-IPv6/URL code can't handle the clean result properly anyway. */
-            src = foundHost;
-            ++src;
-            l = strlen(foundHost);
-            i = 1;
-            for (; i < l && *src != ']' && *src != '\0'; ++i, ++src, ++dst) {
-                *dst = *src;
-            }
-
-            /* we moved in-place, so truncate the actual hostname found */
-            *dst = '\0';
-            ++dst;
-
-            /* skip ahead to either start of port, or original EOS */
-            while (*dst != '\0' && *dst != ':')
-                ++dst;
-            t = dst;
-        } else {
-            t = strrchr(foundHost, ':');
-
-            if (t != strchr(foundHost,':') ) {
-                /* RFC 2732 states IPv6 "SHOULD" be bracketed. allowing for times when its not. */
-                /* RFC 3986 'update' simply modifies this to an "is" with no emphasis at all! */
-                /* therefore we MUST accept the case where they are not bracketed at all. */
-                t = NULL;
-            }
-        }
-
-        // Bug 3183 sanity check: If scheme is present, host must be too.
-        if (protocol != AnyP::PROTO_NONE && foundHost[0] == '\0') {
-            debugs(23, DBG_IMPORTANT, "SECURITY ALERT: Missing hostname in URL '" << url << "'. see access.log for details.");
-            return false;
-        }
-
-        if (t && *t == ':') {
-            *t = '\0';
-            ++t;
-            foundPort = atoi(t);
-        }
-    }
-
-    for (t = foundHost; *t; ++t)
-        *t = xtolower(*t);
-
-    if (stringHasWhitespace(foundHost)) {
-        if (URI_WHITESPACE_STRIP == Config.uri_whitespace) {
-            t = q = foundHost;
-            while (*t) {
-                if (!xisspace(*t)) {
-                    *q = *t;
-                    ++q;
-                }
-                ++t;
-            }
-            *q = '\0';
-        }
-    }
-
-    debugs(23, 3, "Split URL '" << url << "' into proto='" << proto << "', host='" << foundHost << "', port='" << foundPort << "', path='" << urlpath << "'");
-
-    if (Config.onoff.check_hostnames &&
-            strspn(foundHost, Config.onoff.allow_underscore ? valid_hostname_chars_u : valid_hostname_chars) != strlen(foundHost)) {
-        debugs(23, DBG_IMPORTANT, MYNAME << "Illegal character in hostname '" << foundHost << "'");
-        return false;
-    }
-
-    /* For IPV6 addresses also check for a colon */
-    if (Config.appendDomain && !strchr(foundHost, '.') && !strchr(foundHost, ':'))
-        strncat(foundHost, Config.appendDomain, SQUIDHOSTNAMELEN - strlen(foundHost) - 1);
-
-    /* remove trailing dots from hostnames */
-    while ((l = strlen(foundHost)) > 0 && foundHost[--l] == '.')
-        foundHost[l] = '\0';
-
-    /* reject duplicate or leading dots */
-    if (strstr(foundHost, "..") || *foundHost == '.') {
-        debugs(23, DBG_IMPORTANT, MYNAME << "Illegal hostname '" << foundHost << "'");
-        return false;
-    }
-
-    if (foundPort < 1 || foundPort > 65535) {
-        debugs(23, 3, "Invalid port '" << foundPort << "'");
-        return false;
-    }
-
-#if HARDCODE_DENY_PORTS
-    /* These ports are filtered in the default squid.conf, but
-     * maybe someone wants them hardcoded... */
-    if (foundPort == 7 || foundPort == 9 || foundPort == 19) {
-        debugs(23, DBG_CRITICAL, MYNAME << "Deny access to port " << foundPort);
-        return false;
-    }
-#endif
-
-    if (stringHasWhitespace(urlpath)) {
-        debugs(23, 2, "URI has whitespace: {" << url << "}");
-
-        switch (Config.uri_whitespace) {
-
-        case URI_WHITESPACE_DENY:
-            return false;
-
-        case URI_WHITESPACE_ALLOW:
-            break;
-
-        case URI_WHITESPACE_ENCODE:
-            t = rfc1738_escape_unescaped(urlpath);
-            xstrncpy(urlpath, t, MAX_URL);
-            break;
-
-        case URI_WHITESPACE_CHOP:
-            *(urlpath + strcspn(urlpath, w_space)) = '\0';
-            break;
-
-        case URI_WHITESPACE_STRIP:
-        default:
-            t = q = urlpath;
-            while (*t) {
-                if (!xisspace(*t)) {
-                    *q = *t;
-                    ++q;
-                }
-                ++t;
-            }
-            *q = '\0';
-        }
-    }
-
-    parseFinish(protocol, proto, urlpath, foundHost, SBuf(login), foundPort);
-    return true;
-}
-
-/// Update the URL object with parsed URI data.
-void
-URL::parseFinish(const AnyP::ProtocolType protocol,
-                 const char *const protoStr, // for unknown protocols
-                 const char *const aUrlPath,
-                 const char *const aHost,
-                 const SBuf &aLogin,
-                 const int aPort)
-{
-    setScheme(protocol, protoStr);
-    path(aUrlPath);
-    host(aHost);
-    userInfo(aLogin);
-    port(aPort);
-}
-
-void
-URL::touch()
-{
-    absolute_.clear();
-    authorityHttp_.clear();
-    authorityWithPort_.clear();
-}
-
-SBuf &
-URL::authority(bool requirePort) const
-{
-    if (authorityHttp_.isEmpty()) {
-
-        // both formats contain Host/IP
-        authorityWithPort_.append(host());
-        authorityHttp_ = authorityWithPort_;
-
-        // authorityForm_ only has :port if it is non-default
-        authorityWithPort_.appendf(":%u",port());
-        if (port() != getScheme().defaultPort())
-            authorityHttp_ = authorityWithPort_;
-    }
-
-    return requirePort ? authorityWithPort_ : authorityHttp_;
-}
-
-SBuf &
-URL::absolute() const
-{
-    if (absolute_.isEmpty()) {
-        // TODO: most URL will be much shorter, avoid allocating this much
-        absolute_.reserveCapacity(MAX_URL);
-
-        absolute_.append(getScheme().image());
-        absolute_.append(":",1);
-        if (getScheme() != AnyP::PROTO_URN) {
-            absolute_.append("//", 2);
-            const bool omitUserInfo = getScheme() == AnyP::PROTO_HTTP ||
-                                      getScheme() != AnyP::PROTO_HTTPS ||
-                                      userInfo().isEmpty();
-            if (!omitUserInfo) {
-                absolute_.append(userInfo());
-                absolute_.append("@", 1);
-            }
-            absolute_.append(authority());
-        }
-        absolute_.append(path());
-    }
-
-    return absolute_;
-}
-
-/** \todo AYJ: Performance: This is an *almost* duplicate of HttpRequest::effectiveRequestUri(). But elides the query-string.
- *        After copying it on in the first place! Would be less code to merge the two with a flag parameter.
- *        and never copy the query-string part in the first place
- */
-char *
-urlCanonicalClean(const HttpRequest * request)
-{
-    LOCAL_ARRAY(char, buf, MAX_URL);
-
-    snprintf(buf, sizeof(buf), SQUIDSBUFPH, SQUIDSBUFPRINT(request->effectiveRequestUri()));
-    buf[sizeof(buf)-1] = '\0';
-
-    // URN, CONNECT method, and non-stripped URIs can go straight out
-    if (Config.onoff.strip_query_terms && !(request->method == Http::METHOD_CONNECT || request->url.getScheme() == AnyP::PROTO_URN)) {
-        // strip anything AFTER a question-mark
-        // leaving the '?' in place
-        if (auto t = strchr(buf, '?')) {
-            *(++t) = '\0';
-        }
-    }
-
-    if (stringHasCntl(buf))
-        xstrncpy(buf, rfc1738_escape_unescaped(buf), MAX_URL);
-
-    return buf;
-}
-
-/**
- * Yet another alternative to urlCanonical.
- * This one adds the https:// parts to Http::METHOD_CONNECT URL
- * for use in error page outputs.
- * Luckily we can leverage the others instead of duplicating.
- */
-const char *
-urlCanonicalFakeHttps(const HttpRequest * request)
-{
-    LOCAL_ARRAY(char, buf, MAX_URL);
-
-    // method CONNECT and port HTTPS
-    if (request->method == Http::METHOD_CONNECT && request->url.port() == 443) {
-        snprintf(buf, MAX_URL, "https://%s/*", request->url.host());
-        return buf;
-    }
-
-    // else do the normal complete canonical thing.
-    return urlCanonicalClean(request);
-}
-
-/*
- * Test if a URL is relative.
- *
- * RFC 2396, Section 5 (Page 17) implies that in a relative URL, a '/' will
- * appear before a ':'.
- */
-bool
-urlIsRelative(const char *url)
-{
-    const char *p;
-
-    if (url == NULL) {
-        return (false);
-    }
-    if (*url == '\0') {
-        return (false);
-    }
-
-    for (p = url; *p != '\0' && *p != ':' && *p != '/'; ++p);
-
-    if (*p == ':') {
-        return (false);
-    }
-    return (true);
-}
-
-/*
- * Convert a relative URL to an absolute URL using the context of a given
- * request.
- *
- * It is assumed that you have already ensured that the URL is relative.
- *
- * If NULL is returned it is an indication that the method in use in the
- * request does not distinguish between relative and absolute and you should
- * use the url unchanged.
- *
- * If non-NULL is returned, it is up to the caller to free the resulting
- * memory using safe_free().
- */
-char *
-urlMakeAbsolute(const HttpRequest * req, const char *relUrl)
-{
-
-    if (req->method.id() == Http::METHOD_CONNECT) {
-        return (NULL);
-    }
-
-    char *urlbuf = (char *)xmalloc(MAX_URL * sizeof(char));
-
-    if (req->url.getScheme() == AnyP::PROTO_URN) {
-        // XXX: this is what the original code did, but it seems to break the
-        // intended behaviour of this function. It returns the stored URN path,
-        // not converting the given one into a URN...
-        snprintf(urlbuf, MAX_URL, SQUIDSBUFPH, SQUIDSBUFPRINT(req->url.absolute()));
-        return (urlbuf);
-    }
-
-    SBuf authorityForm = req->url.authority(); // host[:port]
-    const SBuf &scheme = req->url.getScheme().image();
-    size_t urllen = snprintf(urlbuf, MAX_URL, SQUIDSBUFPH "://" SQUIDSBUFPH "%s" SQUIDSBUFPH,
-                             SQUIDSBUFPRINT(scheme),
-                             SQUIDSBUFPRINT(req->url.userInfo()),
-                             !req->url.userInfo().isEmpty() ? "@" : "",
-                             SQUIDSBUFPRINT(authorityForm));
-
-    // if the first char is '/' assume its a relative path
-    // XXX: this breaks on scheme-relative URLs,
-    // but we should not see those outside ESI, and rarely there.
-    // XXX: also breaks on any URL containing a '/' in the query-string portion
-    if (relUrl[0] == '/') {
-        xstrncpy(&urlbuf[urllen], relUrl, MAX_URL - urllen - 1);
-    } else {
-        SBuf path = req->url.path();
-        SBuf::size_type lastSlashPos = path.rfind('/');
-
-        if (lastSlashPos == SBuf::npos) {
-            // replace the whole path with the given bit(s)
-            urlbuf[urllen] = '/';
-            ++urllen;
-            xstrncpy(&urlbuf[urllen], relUrl, MAX_URL - urllen - 1);
-        } else {
-            // replace only the last (file?) segment with the given bit(s)
-            ++lastSlashPos;
-            if (lastSlashPos > MAX_URL - urllen - 1) {
-                // XXX: crops bits in the middle of the combined URL.
-                lastSlashPos = MAX_URL - urllen - 1;
-            }
-            SBufToCstring(&urlbuf[urllen], path.substr(0,lastSlashPos));
-            urllen += lastSlashPos;
-            if (urllen + 1 < MAX_URL) {
-                xstrncpy(&urlbuf[urllen], relUrl, MAX_URL - urllen - 1);
-            }
-        }
-    }
-
-    return (urlbuf);
-}
-
-int
-matchDomainName(const char *h, const char *d, uint flags)
-{
-    int dl;
-    int hl;
-
-    const bool hostIncludesSubdomains = (*h == '.');
-    while ('.' == *h)
-        ++h;
-
-    hl = strlen(h);
-
-    if (hl == 0)
-        return -1;
-
-    dl = strlen(d);
-
-    /*
-     * Start at the ends of the two strings and work towards the
-     * beginning.
-     */
-    while (xtolower(h[--hl]) == xtolower(d[--dl])) {
-        if (hl == 0 && dl == 0) {
-            /*
-             * We made it all the way to the beginning of both
-             * strings without finding any difference.
-             */
-            return 0;
-        }
-
-        if (0 == hl) {
-            /*
-             * The host string is shorter than the domain string.
-             * There is only one case when this can be a match.
-             * If the domain is just one character longer, and if
-             * that character is a leading '.' then we call it a
-             * match.
-             */
-
-            if (1 == dl && '.' == d[0])
-                return 0;
-            else
-                return -1;
-        }
-
-        if (0 == dl) {
-            /*
-             * The domain string is shorter than the host string.
-             * This is a match only if the first domain character
-             * is a leading '.'.
-             */
-
-            if ('.' == d[0]) {
-                if (flags & mdnRejectSubsubDomains) {
-                    // Check for sub-sub domain and reject
-                    while(--hl >= 0 && h[hl] != '.');
-                    if (hl < 0) {
-                        // No sub-sub domain found, but reject if there is a
-                        // leading dot in given host string (which is removed
-                        // before the check is started).
-                        return hostIncludesSubdomains ? 1 : 0;
-                    } else
-                        return 1; // sub-sub domain, reject
-                } else
-                    return 0;
-            } else
-                return 1;
-        }
-    }
-
-    /*
-     * We found different characters in the same position (from the end).
-     */
-
-    // If the h has a form of "*.foo.com" and d has a form of "x.foo.com"
-    // then the h[hl] points to '*', h[hl+1] to '.' and d[dl] to 'x'
-    // The following checks are safe, the "h[hl + 1]" in the worst case is '\0'.
-    if ((flags & mdnHonorWildcards) && h[hl] == '*' && h[hl + 1] == '.')
-        return 0;
-
-    /*
-     * If one of those character is '.' then its special.  In order
-     * for splay tree sorting to work properly, "x-foo.com" must
-     * be greater than ".foo.com" even though '-' is less than '.'.
-     */
-    if ('.' == d[dl])
-        return 1;
-
-    if ('.' == h[hl])
-        return -1;
-
-    return (xtolower(h[hl]) - xtolower(d[dl]));
-}
-
-/*
- * return true if we can serve requests for this method.
- */
-int
-urlCheckRequest(const HttpRequest * r)
-{
-    int rc = 0;
-    /* protocol "independent" methods
-     *
-     * actually these methods are specific to HTTP:
-     * they are methods we recieve on our HTTP port,
-     * and if we had a FTP listener would not be relevant
-     * there.
-     *
-     * So, we should delegate them to HTTP. The problem is that we
-     * do not have a default protocol from the client side of HTTP.
-     */
-
-    if (r->method == Http::METHOD_CONNECT)
-        return 1;
-
-    // we support OPTIONS and TRACE directed at us (with a 501 reply, for now)
-    // we also support forwarding OPTIONS and TRACE, except for the *-URI ones
-    if (r->method == Http::METHOD_OPTIONS || r->method == Http::METHOD_TRACE)
-        return (r->header.getInt64(Http::HdrType::MAX_FORWARDS) == 0 || r->url.path() != URL::Asterisk());
-
-    if (r->method == Http::METHOD_PURGE)
-        return 1;
-
-    /* does method match the protocol? */
-    switch (r->url.getScheme()) {
-
-    case AnyP::PROTO_URN:
-
-    case AnyP::PROTO_HTTP:
-
-    case AnyP::PROTO_CACHE_OBJECT:
-        rc = 1;
-        break;
-
-    case AnyP::PROTO_FTP:
-
-        if (r->method == Http::METHOD_PUT)
-            rc = 1;
-
-    case AnyP::PROTO_GOPHER:
-
-    case AnyP::PROTO_WAIS:
-
-    case AnyP::PROTO_WHOIS:
-        if (r->method == Http::METHOD_GET)
-            rc = 1;
-        else if (r->method == Http::METHOD_HEAD)
-            rc = 1;
-
-        break;
-
-    case AnyP::PROTO_HTTPS:
-#if USE_OPENSSL
-        rc = 1;
-#elif USE_GNUTLS
-        rc = 1;
-#else
-        /*
-        * Squid can't originate an SSL connection, so it should
-        * never receive an "https:" URL.  It should always be
-        * CONNECT instead.
-        */
-        rc = 0;
-#endif
-        break;
-
-    default:
-        break;
-    }
-
-    return rc;
-}
-
-/*
- * Quick-n-dirty host extraction from a URL.  Steps:
- *      Look for a colon
- *      Skip any '/' after the colon
- *      Copy the next SQUID_MAXHOSTNAMELEN bytes to host[]
- *      Look for an ending '/' or ':' and terminate
- *      Look for login info preceeded by '@'
- */
-
-class URLHostName
-{
-
-public:
-    char * extract(char const *url);
-
-private:
-    static char Host [SQUIDHOSTNAMELEN];
-    void init(char const *);
-    void findHostStart();
-    void trimTrailingChars();
-    void trimAuth();
-    char const *hostStart;
-    char const *url;
-};
-
-char *
-urlHostname(const char *url)
-{
-    return URLHostName().extract(url);
-}
-
-char URLHostName::Host[SQUIDHOSTNAMELEN];
-
-void
-URLHostName::init(char const *aUrl)
-{
-    Host[0] = '\0';
-    url = aUrl;
-}
-
-void
-URLHostName::findHostStart()
-{
-    if (NULL == (hostStart = strchr(url, ':')))
-        return;
-
-    ++hostStart;
-
-    while (*hostStart != '\0' && *hostStart == '/')
-        ++hostStart;
-
-    if (*hostStart == ']')
-        ++hostStart;
-}
-
-void
-URLHostName::trimTrailingChars()
-{
-    char *t;
-
-    if ((t = strchr(Host, '/')))
-        *t = '\0';
-
-    if ((t = strrchr(Host, ':')))
-        *t = '\0';
-
-    if ((t = strchr(Host, ']')))
-        *t = '\0';
-}
-
-void
-URLHostName::trimAuth()
-{
-    char *t;
-
-    if ((t = strrchr(Host, '@'))) {
-        ++t;
-        memmove(Host, t, strlen(t) + 1);
-    }
-}
-
-char *
-URLHostName::extract(char const *aUrl)
-{
-    init(aUrl);
-    findHostStart();
-
-    if (hostStart == NULL)
-        return NULL;
-
-    xstrncpy(Host, hostStart, SQUIDHOSTNAMELEN);
-
-    trimTrailingChars();
-
-    trimAuth();
-
-    return Host;
-}
-
-URL::URL(AnyP::UriScheme const &aScheme) :
-    scheme_(aScheme),
-    hostIsNumeric_(false),
-    port_(0)
-{
-    *host_=0;
-}
-
diff -u -r -N squid-4.0.25/src/URL.h squid-4.1/src/URL.h
--- squid-4.0.25/src/URL.h	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/URL.h	1970-01-01 12:00:00.000000000 +1200
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef SQUID_SRC_URL_H
-#define SQUID_SRC_URL_H
-
-#include "anyp/UriScheme.h"
-#include "ip/Address.h"
-#include "rfc2181.h"
-#include "sbuf/SBuf.h"
-
-#include <iosfwd>
-
-/**
- * The URL class represents a Uniform Resource Location
- *
- * Governed by RFC 3986
- */
-class URL
-{
-    MEMPROXY_CLASS(URL);
-
-public:
-    URL() : hostIsNumeric_(false), port_(0) {*host_=0;}
-    URL(AnyP::UriScheme const &aScheme);
-    URL(const URL &other) {
-        this->operator =(other);
-    }
-    URL &operator =(const URL &o) {
-        scheme_ = o.scheme_;
-        userInfo_ = o.userInfo_;
-        memcpy(host_, o.host_, sizeof(host_));
-        hostIsNumeric_ = o.hostIsNumeric_;
-        hostAddr_ = o.hostAddr_;
-        port_ = o.port_;
-        path_ = o.path_;
-        touch();
-        return *this;
-    }
-
-    void clear() {
-        scheme_=AnyP::PROTO_NONE;
-        hostIsNumeric_ = false;
-        *host_ = 0;
-        hostAddr_.setEmpty();
-        port_ = 0;
-        touch();
-    }
-    void touch(); ///< clear the cached URI display forms
-
-    bool parse(const HttpRequestMethod &, const char *url);
-
-    AnyP::UriScheme const & getScheme() const {return scheme_;}
-
-    /// convert the URL scheme to that given
-    void setScheme(const AnyP::ProtocolType &p, const char *str) {
-        scheme_ = AnyP::UriScheme(p, str);
-        touch();
-    }
-
-    void userInfo(const SBuf &s) {userInfo_=s; touch();}
-    const SBuf &userInfo() const {return userInfo_;}
-
-    void host(const char *src);
-    const char *host(void) const {return host_;}
-    int hostIsNumeric(void) const {return hostIsNumeric_;}
-    Ip::Address const & hostIP(void) const {return hostAddr_;}
-
-    void port(unsigned short p) {port_=p; touch();}
-    unsigned short port() const {return port_;}
-
-    void path(const char *p) {path_=p; touch();}
-    void path(const SBuf &p) {path_=p; touch();}
-    const SBuf &path() const;
-
-    /// the static '/' default URL-path
-    static const SBuf &SlashPath();
-
-    /// the static '*' pseudo-URL
-    static const SBuf &Asterisk();
-
-    /**
-     * The authority-form URI for currently stored values.
-     *
-     * As defined by RFC 7230 section 5.3.3 this form omits the
-     * userinfo@ field from RFC 3986 defined authority segment.
-     *
-     * \param requirePort when true the port will be included, otherwise
-     *                    port will be elided when it is the default for
-     *                    the current scheme.
-     */
-    SBuf &authority(bool requirePort = false) const;
-
-    /**
-     * The absolute-form URI for currently stored values.
-     *
-     * As defined by RFC 7230 section 5.3.3 this form omits the
-     * userinfo@ field from RFC 3986 defined authority segments
-     * when the protocol scheme is http: or https:.
-     */
-    SBuf &absolute() const;
-
-private:
-    void parseFinish(const AnyP::ProtocolType, const char *const, const char *const, const char *const, const SBuf &, const int);
-
-    /**
-     \par
-     * The scheme of this URL. This has the 'type code' smell about it.
-     * In future we may want to make the methods that dispatch based on
-     * the scheme virtual and have a class per protocol.
-     \par
-     * On the other hand, having Protocol as an explicit concept is useful,
-     * see for instance the ACLProtocol acl type. One way to represent this
-     * is to have one prototype URL with no host etc for each scheme,
-     * another is to have an explicit scheme class, and then each URL class
-     * could be a subclass of the scheme. Another way is one instance of
-     * a AnyP::UriScheme class instance for each URL scheme we support, and one URL
-     * class for each manner of treating the scheme : a Hierarchical URL, a
-     * non-hierarchical URL etc.
-     \par
-     * Deferring the decision, its a type code for now. RBC 20060507.
-     \par
-     * In order to make taking any of these routes easy, scheme is private
-     * and immutable, only settable at construction time,
-     */
-    AnyP::UriScheme scheme_;
-
-    SBuf userInfo_; // aka 'URL-login'
-
-    // XXX: uses char[] instead of SBUf to reduce performance regressions
-    //      from c_str() since most code using this is not yet using SBuf
-    char host_[SQUIDHOSTNAMELEN];   ///< string representation of the URI authority name or IP
-    bool hostIsNumeric_;            ///< whether the authority 'host' is a raw-IP
-    Ip::Address hostAddr_;          ///< binary representation of the URI authority if it is a raw-IP
-
-    unsigned short port_;   ///< URL port
-
-    // XXX: for now includes query-string.
-    SBuf path_;     ///< URL path segment
-
-    // pre-assembled URL forms
-    mutable SBuf authorityHttp_;     ///< RFC 7230 section 5.3.3 authority, maybe without default-port
-    mutable SBuf authorityWithPort_; ///< RFC 7230 section 5.3.3 authority with explicit port
-    mutable SBuf absolute_;          ///< RFC 7230 section 5.3.2 absolute-URI
-};
-
-inline std::ostream &
-operator <<(std::ostream &os, const URL &url)
-{
-    // none means explicit empty string for scheme.
-    if (url.getScheme() != AnyP::PROTO_NONE)
-        os << url.getScheme().image();
-    os << ":";
-
-    // no authority section on URN
-    if (url.getScheme() != AnyP::PROTO_URN)
-        os << "//" << url.authority();
-
-    // path is what it is - including absent
-    os << url.path();
-    return os;
-}
-
-class HttpRequest;
-class HttpRequestMethod;
-
-void urlInitialize(void);
-char *urlCanonicalClean(const HttpRequest *);
-const char *urlCanonicalFakeHttps(const HttpRequest * request);
-bool urlIsRelative(const char *);
-char *urlMakeAbsolute(const HttpRequest *, const char *);
-char *urlRInternal(const char *host, unsigned short port, const char *dir, const char *name);
-char *urlInternal(const char *dir, const char *name);
-
-enum MatchDomainNameFlags {
-    mdnNone = 0,
-    mdnHonorWildcards = 1 << 0,
-    mdnRejectSubsubDomains = 1 << 1
-};
-
-/**
- * matchDomainName() matches a hostname (usually extracted from traffic)
- * with a domainname when mdnNone or mdnRejectSubsubDomains flags are used
- * according to the following rules:
- *
- *    HOST      |   DOMAIN    |   mdnNone | mdnRejectSubsubDomains
- * -------------|-------------|-----------|-----------------------
- *      foo.com |   foo.com   |     YES   |   YES
- *     .foo.com |   foo.com   |     YES   |   YES
- *    x.foo.com |   foo.com   |     NO    |   NO
- *      foo.com |  .foo.com   |     YES   |   YES
- *     .foo.com |  .foo.com   |     YES   |   YES
- *    x.foo.com |  .foo.com   |     YES   |   YES
- *   .x.foo.com |  .foo.com   |     YES   |   NO
- *  y.x.foo.com |  .foo.com   |     YES   |   NO
- *
- * if mdnHonorWildcards flag is set then the matchDomainName() also accepts
- * optional wildcards on hostname:
- *
- *    HOST      |    DOMAIN    |  MATCH?
- * -------------|--------------|-------
- *    *.foo.com |   x.foo.com  |   YES
- *    *.foo.com |  .x.foo.com  |   YES
- *    *.foo.com |    .foo.com  |   YES
- *    *.foo.com |     foo.com  |   NO
- *
- * The combination of mdnHonorWildcards and mdnRejectSubsubDomains flags is
- * supported.
- *
- * \retval 0 means the host matches the domain
- * \retval 1 means the host is greater than the domain
- * \retval -1 means the host is less than the domain
- */
-int matchDomainName(const char *host, const char *domain, uint flags = mdnNone);
-int urlCheckRequest(const HttpRequest *);
-char *urlHostname(const char *url);
-void urlExtMethodConfigure(void);
-
-#endif /* SQUID_SRC_URL_H_H */
-
diff -u -r -N squid-4.0.25/src/urn.cc squid-4.1/src/urn.cc
--- squid-4.0.25/src/urn.cc	2018-06-12 04:30:57.000000000 +1200
+++ squid-4.1/src/urn.cc	2018-07-02 15:26:07.000000000 +1200
@@ -23,7 +23,6 @@
 #include "Store.h"
 #include "StoreClient.h"
 #include "tools.h"
-#include "URL.h"
 #include "urn.h"
 
 #define URN_REQBUF_SZ   4096
@@ -145,7 +144,7 @@
     }
 
     SBuf uri = r->url.path();
-    // TODO: use class URL instead of generating a string and re-parsing
+    // TODO: use class AnyP::Uri instead of generating a string and re-parsing
     LOCAL_ARRAY(char, local_urlres, 4096);
     char *host = getHost(uri);
     snprintf(local_urlres, 4096, "http://%s/uri-res/N2L?urn:" SQUIDSBUFPH, host, SQUIDSBUFPRINT(uri));
diff -u -r -N squid-4.0.25/tools/helper-mux/helper-mux.8 squid-4.1/tools/helper-mux/helper-mux.8
--- squid-4.0.25/tools/helper-mux/helper-mux.8	2018-06-12 04:56:22.000000000 +1200
+++ squid-4.1/tools/helper-mux/helper-mux.8	2018-07-02 15:39:09.000000000 +1200
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "HELPER-MUX 8"
-.TH HELPER-MUX 8 "2018-06-11" "perl v5.26.2" "User Contributed Perl Documentation"
+.TH HELPER-MUX 8 "2018-07-02" "perl v5.26.2" "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
