This patch makes Squid deal with responses having more than 4KB of
responseline + headers.

- Make the HTTP protocol handler continue reading the response until all
is received. This involves growing the header buffer as needed until the
header fits (or limit reached). Previously the buffer based flow control
made Squid stop reading the response when reaching 4KB 

- makes client_side_reply clone the already parsed HTTP response and
skip over the ascii HTTP header received from the store, similar to the
change Adrian did earlier in Squid-2 but for other reasons.

# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: [EMAIL PROTECTED]
#   m06h0iqek6nq8fyb
# target_branch: /data/bzr/squid3/branches/SQUID_3_0
# testament_sha1: c5c5604c9077c76cd2fc94aecdb4620126c26299
# timestamp: 2008-03-30 18:45:34 +0200
# source_branch: http://www.henriknordstrom.net/bzr/squid3/hno\
#   /largeresp-3.0
# base_revision_id: [EMAIL PROTECTED]
#   nxa2s3jig4ce6nwb
# 
# Begin patch
=== modified file 'src/HttpReply.cc'
--- src/HttpReply.cc	2007-11-26 20:09:54 +0000
+++ src/HttpReply.cc	2008-03-30 14:29:57 +0000
@@ -496,3 +496,17 @@
 
     return expectBody;
 }
+
+HttpReply *
+HttpReply::clone() const
+{
+    HttpReply *rep = new HttpReply();
+    rep->header.append(&header);
+    rep->hdrCacheInit();
+    rep->hdr_sz = hdr_sz;
+    rep->http_ver = http_ver;
+    rep->pstate = pstate;
+    rep->protocol = protocol;
+    rep->sline = sline;
+    return rep;
+}

=== modified file 'src/HttpReply.h'
--- src/HttpReply.h	2007-08-13 23:20:50 +0000
+++ src/HttpReply.h	2008-03-30 14:29:57 +0000
@@ -122,6 +122,11 @@
 
     void packHeadersInto(Packer * p) const;
 
+    /// Clone this reply.
+    /// Could be done as a copy-contructor but we do not want to
+    /// accidently copy a HttpReply..
+    HttpReply *clone() const;
+
 private:
     /* initialize */
     void init();

=== modified file 'src/client_side_reply.cc'
--- src/client_side_reply.cc	2008-03-14 04:45:16 +0000
+++ src/client_side_reply.cc	2008-03-30 14:29:57 +0000
@@ -352,68 +352,47 @@
         sendClientOldEntry();
     }
 
-    // we have a partial reply from the origin
-    else if (STORE_PENDING == http->storeEntry()->store_status && 0 == status) {
-        // header is too large, send old entry
-
-        if (reqsize >= HTTP_REQBUF_SZ) {
-            debugs(88, 3, "handleIMSReply: response from origin is too large '" << http->storeEntry()->url() << "', sending old entry to client" );
-            http->logType = LOG_TCP_REFRESH_FAIL;
-            sendClientOldEntry();
-        }
-
-        // everything looks fine, we're just waiting for more data
-        else {
-            debugs(88, 3, "handleIMSReply: incomplete headers for '" << http->storeEntry()->url() << "', waiting for more data" );
-            reqofs = reqsize;
-            waitForMoreData();
-        }
-    }
-
-    // we have a reply from the origin
+    HttpReply *old_rep = (HttpReply *) old_entry->getReply();
+
+    // origin replied 304
+
+    if (status == HTTP_NOT_MODIFIED) {
+	http->logType = LOG_TCP_REFRESH_UNMODIFIED;
+
+	// update headers on existing entry
+	HttpReply *old_rep = (HttpReply *) old_entry->getReply();
+	old_rep->updateOnNotModified(http->storeEntry()->getReply());
+	old_entry->timestampsSet();
+
+	// if client sent IMS
+
+	if (http->request->flags.ims) {
+	    // forward the 304 from origin
+	    debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and forwarding 304 to client");
+	    sendClientUpstreamResponse();
+	} else {
+	    // send existing entry, it's still valid
+	    debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and sending " <<
+		   old_rep->sline.status << " to client");
+	    sendClientOldEntry();
+	}
+    }
+
+    // origin replied with a non-error code
+    else if (status > HTTP_STATUS_NONE && status < HTTP_INTERNAL_SERVER_ERROR) {
+	// forward response from origin
+	http->logType = LOG_TCP_REFRESH_MODIFIED;
+	debugs(88, 3, "handleIMSReply: origin replied " << status << ", replacing existing entry and forwarding to client");
+	sendClientUpstreamResponse();
+    }
+
+    // origin replied with an error
     else {
-        HttpReply *old_rep = (HttpReply *) old_entry->getReply();
-
-        // origin replied 304
-
-        if (status == HTTP_NOT_MODIFIED) {
-            http->logType = LOG_TCP_REFRESH_UNMODIFIED;
-
-            // update headers on existing entry
-            HttpReply *old_rep = (HttpReply *) old_entry->getReply();
-            old_rep->updateOnNotModified(http->storeEntry()->getReply());
-            old_entry->timestampsSet();
-
-            // if client sent IMS
-
-            if (http->request->flags.ims) {
-                // forward the 304 from origin
-                debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and forwarding 304 to client");
-                sendClientUpstreamResponse();
-            } else {
-                // send existing entry, it's still valid
-                debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and sending " <<
-                       old_rep->sline.status << " to client");
-                sendClientOldEntry();
-            }
-        }
-
-        // origin replied with a non-error code
-        else if (status > HTTP_STATUS_NONE && status < HTTP_INTERNAL_SERVER_ERROR) {
-            // forward response from origin
-            http->logType = LOG_TCP_REFRESH_MODIFIED;
-            debugs(88, 3, "handleIMSReply: origin replied " << status << ", replacing existing entry and forwarding to client");
-            sendClientUpstreamResponse();
-        }
-
-        // origin replied with an error
-        else {
-            // ignore and let client have old entry
-            http->logType = LOG_TCP_REFRESH_FAIL;
-            debugs(88, 3, "handleIMSReply: origin replied with error " <<
-                   status << ", sending old entry (" << old_rep->sline.status << ") to client");
-            sendClientOldEntry();
-        }
+	// ignore and let client have old entry
+	http->logType = LOG_TCP_REFRESH_FAIL;
+	debugs(88, 3, "handleIMSReply: origin replied with error " <<
+	       status << ", sending old entry (" << old_rep->sline.status << ") to client");
+	sendClientOldEntry();
     }
 }
 
@@ -472,33 +451,6 @@
     /* update size of the request */
     reqsize = result.length + reqofs;
 
-    if (e->getReply()->sline.status == 0) {
-        /*
-         * we don't have full reply headers yet; either wait for more or
-         * punt to clientProcessMiss.
-         */
-
-        if (e->mem_status == IN_MEMORY || e->store_status == STORE_OK) {
-            processMiss();
-        } else if (result.length + reqofs >= HTTP_REQBUF_SZ
-                   && http->out.offset == 0) {
-            processMiss();
-        } else {
-            debugs(88, 3, "clientCacheHit: waiting for HTTP reply headers");
-            reqofs += result.length;
-            assert(reqofs <= HTTP_REQBUF_SZ);
-            /* get the next users' buffer */
-            StoreIOBuffer tempBuffer;
-            tempBuffer.offset = http->out.offset + reqofs;
-            tempBuffer.length = next()->readBuffer.length - reqofs;
-            tempBuffer.data = next()->readBuffer.data + reqofs;
-            storeClientCopy(sc, e,
-                            tempBuffer, CacheHit, this);
-        }
-
-        return;
-    }
-
     /*
      * Got the headers, now grok them
      */
@@ -1371,32 +1323,14 @@
 
 
 void
-clientReplyContext::buildReply(const char *buf, size_t size)
+clientReplyContext::cloneReply()
 {
-    size_t k = headersEnd(buf, size);
-
-    if (!k)
-        return;
-
     assert(reply == NULL);
 
-    HttpReply *rep = new HttpReply;
+    HttpReply *rep = http->storeEntry()->getReply()->clone();
 
     reply = HTTPMSGLOCK(rep);
 
-    if (!reply->parseCharBuf(buf, k)) {
-        /* parsing failure, get rid of the invalid reply */
-        HTTPMSGUNLOCK(reply);
-
-        if (http->request->range) {
-            debugs(0,0,HERE << "look for bug here");
-            /* this will fail and destroy request->range */
-            //          clientBuildRangeHeader(http, reply);
-        }
-
-        return;
-    }
-
     /* enforce 1.0 reply version */
     reply->sline.version = HttpVersion(1,0);
 
@@ -1703,32 +1637,6 @@
     return getNextNode();
 }
 
-void
-clientReplyContext::waitForMoreData ()
-{
-    debugs(88, 5, "clientReplyContext::waitForMoreData: Waiting for more data to parse reply headers in client side.");
-    /* We don't have enough to parse the metadata yet */
-    /* TODO: the store should give us out of band metadata and
-     * obsolete this routine 
-     */
-    /* wait for more to arrive */
-    startSendProcess();
-}
-
-void
-clientReplyContext::startSendProcess()
-{
-    debugs(88, 5, "clientReplyContext::startSendProcess: triggering store read to SendMoreData");
-    assert(reqofs <= HTTP_REQBUF_SZ);
-    /* TODO: copy into the supplied buffer */
-    StoreIOBuffer tempBuffer;
-    tempBuffer.offset = reqofs;
-    tempBuffer.length = next()->readBuffer.length - reqofs;
-    tempBuffer.data = next()->readBuffer.data + reqofs;
-    storeClientCopy(sc, http->storeEntry(),
-                    tempBuffer, SendMoreData, this);
-}
-
 /*
  * Calculates the maximum size allowed for an HTTP response
  */
@@ -1841,8 +1749,10 @@
     http->loggingEntry(http->storeEntry());
 
     ssize_t body_size = reqofs - reply->hdr_sz;
-
-    assert(body_size >= 0);
+    if (body_size < 0) {
+	reqofs = reply->hdr_sz;
+	body_size = 0;
+    }
 
     debugs(88, 3, "clientReplyContext::sendMoreData: Appending " <<
            (int) body_size << " bytes after " << reply->hdr_sz <<
@@ -1872,7 +1782,7 @@
 
     StoreIOBuffer tempBuffer;
     char *buf = next()->readBuffer.data;
-    char *body_buf = buf + reply->hdr_sz;
+    char *body_buf = buf + reply->hdr_sz - next()->readBuffer.offset;
 
     //Server side may disable ranges under some circumstances.
 
@@ -1916,23 +1826,11 @@
 
     char *body_buf = buf;
 
-    /* This is always valid until we get the headers as metadata from
-     * storeClientCopy. 
-     * Then it becomes reqofs == next->readBuffer.offset()
-     */
-    assert(reqofs == 0 || flags.storelogiccomplete);
-
-    if (flags.headersSent && buf != result.data) {
+    if (buf != result.data) {
         /* we've got to copy some data */
         assert(result.length <= next()->readBuffer.length);
         xmemcpy(buf, result.data, result.length);
         body_buf = buf;
-    } else if (!flags.headersSent &&
-               buf + reqofs !=result.data) {
-        /* we've got to copy some data */
-        assert(result.length + reqofs <= next()->readBuffer.length);
-        xmemcpy(buf + reqofs, result.data, result.length);
-        body_buf = buf;
     }
 
     /* We've got the final data to start pushing... */
@@ -1971,38 +1869,23 @@
         return;
     }
 
-    buildReply(buf, reqofs);
-
-    if (reply) {
-
-        /* handle headers */
-
-        if (Config.onoff.log_mime_hdrs) {
-            size_t k;
-
-            if ((k = headersEnd(buf, reqofs))) {
-                safe_free(http->al.headers.reply);
-                http->al.headers.reply = (char *)xcalloc(k + 1, 1);
-                xstrncpy(http->al.headers.reply, buf, k);
-            }
-        }
-
-        holdingBuffer = result;
-        processReplyAccess();
-        return;
-
-    } else if (reqofs < HTTP_REQBUF_SZ && entry->store_status == STORE_PENDING) {
-        waitForMoreData();
-        return;
-    } else {
-        debugs(88, 0, "clientReplyContext::sendMoreData: Unable to parse reply headers within a single HTTP_REQBUF_SZ length buffer");
-        StoreIOBuffer tempBuffer;
-        tempBuffer.flags.error = 1;
-        /* XXX FIXME: make an html error page here */
-        sendStreamError(tempBuffer);
-        return;
+    cloneReply();
+
+    /* handle headers */
+
+    if (Config.onoff.log_mime_hdrs) {
+	size_t k;
+
+	if ((k = headersEnd(buf, reqofs))) {
+	    safe_free(http->al.headers.reply);
+	    http->al.headers.reply = (char *)xcalloc(k + 1, 1);
+	    xstrncpy(http->al.headers.reply, buf, k);
+	}
     }
-    fatal ("clientReplyContext::sendMoreData: Unreachable code reached \n");
+
+    holdingBuffer = result;
+    processReplyAccess();
+    return;
 }
 
 

=== modified file 'src/client_side_reply.h'
--- src/client_side_reply.h	2008-02-26 06:08:50 +0000
+++ src/client_side_reply.h	2008-03-30 14:29:57 +0000
@@ -124,15 +124,13 @@
     bool errorInStream(StoreIOBuffer const &result, size_t const &sizeToProcess)const ;
     void sendStreamError(StoreIOBuffer const &result);
     void pushStreamData(StoreIOBuffer const &result, char *source);
-    void waitForMoreData ();
     clientStreamNode * next() const;
-    void startSendProcess();
     StoreIOBuffer holdingBuffer;
     HttpReply *reply;
     void processReplyAccess();
     static PF ProcessReplyAccessResult;
     void processReplyAccessResult(bool accessAllowed);
-    void buildReply(const char *buf, size_t size);
+    void cloneReply();
     void buildReplyHeader ();
     bool alwaysAllowResponse(http_status sline) const;
     int checkTransferDone();

=== modified file 'src/http.cc'
--- src/http.cc	2007-11-19 05:00:58 +0000
+++ src/http.cc	2008-03-30 16:38:00 +0000
@@ -1213,12 +1213,16 @@
      * handler until we get a notification from someone that
      * its okay to read again.
      */
-    if (read_sz < 2)
-        return;
+    if (read_sz < 2) {
+	if (flags.headers_parsed)
+	    return;
+	else
+	    read_sz = 1024;
+    }
 
     if (flags.do_next_read) {
-        flags.do_next_read = 0;
-        entry->delayAwareRead(fd, readBuf->space(), read_sz, ReadReplyWrapper, this);
+	flags.do_next_read = 0;
+	entry->delayAwareRead(fd, readBuf->space(read_sz), read_sz, ReadReplyWrapper, this);
     }
 }
 

# Begin bundle
IyBCYXphYXIgcmV2aXNpb24gYnVuZGxlIHY0CiMKQlpoOTFBWSZTWQoOMgwACBjfgEgwef///3/v
/4C////6YA49b7lGasq+zF2ZKGqNsb03TpvZ3s7s0JWgDShdBhoYoSZMmU0yGJhlPU9Ro0xNAAAN
DQA0Bkmk0xNEzEqe0iAPUDQeoAGmjQNANBoONGTIwjEAwmgwCaDQMmTRkyGEBhIiCFDTEyp6eFHk
U08mo9QyAaGgBoB6gBFJJmkaDJMjVPwknpp6mnpNoTU/RTE00NqaNAA0EigQ0BCYIGgU8RomJqG1
GjTTTID1DTTSiSRRCoxC8n+nr+rq+vRWVaL+N/5VG+MrVbqQxsHlR/hNdVE8zzhUnZRfD0MarJqk
Yx4/DGbntFHHfWUeYyic5zA04L0ZdRJb9og2KzBC1YY0IEEsYxhQgOKBqy1yhCT23xJ+TERtgN0j
BYsq97Cr9JQtYLCtlV46crqth5N4w4sWwbq/DP1ISAy6mm0DGNibAbabYMjZ69/X1h3hT4vZ/de1
iegY2a2oq//jgj5y/T2oP8o6kMbG20gbG9McDzA5x+Tbtw0ZDIHr+HLDDHBccIUOj4D4XpKL0vMF
WQREFFevPQgtFnxpGAyAmImkTyhu7N8GPLYg0yZUyygoc0UnljDk17fYGDPA289rNbI223PwtlSI
PdOnZ2Obl6TTI+nodWkv1eijBErF+Mq7gHN2le6I5XDv9aAQB+CMK2ESpvGJyDjttYO8+jShRwse
aB02hoiUL/VlS/PYevo38DjrYx6ZIyNZubS843S2dWkyRajoTGwStbznejG6MAQ9j1Bemyld6uGL
xKRfJCc923b/PH2W5a3n2P6lcq+p+z09x5DwROyLm7wyl9NlPdTSzDS/M3AzsEjC+GS3KoBYGkh8
Xgnqah+J+bYMKMiIUOHtlhRFW3NIl6rxVlJ6Gdxxx3/t9mvTX27Rj52Gep10lE2wRY16mGWrvYLp
CusMcTo5s849JDK+pvQZw8+luTqDvVefcu1MEutLFMaz6aQQS22lDDUyL4mxR7kvTdPd8ElAXBJ0
NaiqKZKZb+vXCdjSVaKTEwFpXIdzIt6RA468/O1MHLyg+yHvlAwbXBByHizYBENx3UPeSWrbreII
2MSbXS1DJ8tgmp7kiam169ikURvYFmAjeRRGGNVIJRiOwZalMj4XlhTkMJxGIDgoK9l5YzwSsr3Q
mUMJKBNdQsbFEyGTGWkFWYIL60VZYnoXIoO1l+o/LWuYmWwLjdG8/Ul4CyOPl8chBr1OFD0txlWh
YZs1w7hql07k5QzAgOgr6ZIGlSosFso4a3qlalhkFtJiDekkLQjMdABqECT1Ey6hkTStlfnZMU++
kA4wIE2HhE2GM5yHU2oK2wimswJHZ0GZZA3mJWdxjEnhCDcd+qhHClF6qksG0kF+hWHdVFooZFGk
6NmokiSEFEEhLIkkljILAWoaTlvzXzDMCxchlaQzuhYXkLHmMwiPHJGM08kEFN4D2gWqWaSkUYKZ
YRMDAgYFTAkHJJQ80tqrnK3XnnST0zjA82OGASIlVoWDOpBLYSXFnqM0syZUTkBsGYklC7GEQScC
ZUtLDWX2YXpRtJQY3mJ5kdhKka52YFnKpoYEyYUGSPLnXmti28sqZzrqx2zNhsLrVYyW652kNZaQ
AoM0K7jRXm4okpwInMW33F1pb1SIk0tpEroXIMbtHvyMgJ/C4ieBmNpOYiMEyuXVRL1xXGcXPoC2
2AS7QWh+bBeB5XyvklYWYlFklkikKWUpU3FqqWJLHKhEuwF+Z3cMBETGsYhg8mgwGQlv9cnGlM6w
GIYFsUlQqLlaSruJOks6ELpJQlqD6CtmxbuGKud7gDXANiDVeW26ExlTQ1FRdwtq2ReSsSTNMzfR
e0e16KwgNk7oE7JaiUnZqssNRmZYnQR1FlEiJMgFStZlS8zHUlPKVSwy5L6M5SpleyV5C8q9C0Cu
QCCooHLaLeYnQaNjZeEiEgSsHhwdz9kIUDPCBWtmaR/xE2FywFSgyYzEmaFgdYucrU9OSSpwtDmi
a85RYYNEhmTUO4lYaFCFMIrQr6x16i21JMtwSkY2dZ1EIzMCpUl0FJoMTMmXESZyS6ygZljDiDlE
eaZW0cJmZamKVAHBIpmAzoVvQDf4PW1A8AHVpGkJ5jEX7OO4xwjhlgJyA0FBruolFKgDQH0ppQL0
sF9rLLkMRNdI01mUG6YCG4GaAaGyWBftPlTa3rvUEqylS1dWhUXwAKJpLeICS7f6fP8sD512g2mN
pNs+/T2PhaaqBl4LmPPKfzhJh4zdw8n9ac5jUHPMjI3mJ0N+I4/cioTJ/nwXqXzpoGb8tJKczdJH
E7t2zGwpcuz8l7Ffc6mXQf7T4ZYrYuNWsrn4gQvTbgFwPpl0/yNWFVWIR0oIWnRqn7NitOc79KqK
8+xdbFnfZI0DVWcup2DaFxBEBLFDBafhtlMKIoKX9baJjAY0edBsZTqOhT5g+suAPvX3fvJmBU8T
3FD5YYxXj8o2gshpF5S8T4UBmAYHgPyPwfEawB7NyDQCdxQDQj68jVGxpGYpakT6114IiGFrqxHj
xmCA1n3nvNRnPE+0+BUQ/E5DOPG4/A5jAwLCQy8obtD8TtP8fb9uahZ8XDtCH8EgM1s2+nciQoKU
uAzMgddT1rd6bTefQgqfX45lQUhIHa8xzP1qDtWeymBZfYHgLQLrfgglRLhZC/qKQILaznz3Dy5t
4Z9UsuqFGRwbhQTB47LgatZ2Gw7DA8DxJl5XsLihQiXmSCZIwSO0gWE1EoGZMuBECYYEGAw3+hMu
Lzh2WDJi8ege8xOmmanGZgxAWW6Ii6SaFdXFFTtGaIZ1omrBuk4rj+6IzhghWC/VIhVJgx5GvuQS
Ve7GXCAhuaGzOOk5ztOws29PfWuy6h1GKw5Ejm1cUNe8DeK7cxUT4m4N8o2qdtEWgqirvLfkdZAg
wwSGUCRsC38csqA1bQmV5oSR8w1DuaPP0bbbOeB097eBAoyKMUMVetBclf9SoAjcA2A0Ntg2hgNT
6LMXB8ZdS3B9xlieWlwF4LSjQYiyHxOsW5hE6+S/cwAu0CXcUQBM0Q9baFcvMvyQMfOEUorfAO82
HYSN31HaTPE8TzKnv91TIxLic+XdSrgKwOSDfvPSZwM5jCnKt7RwPkncmtN13dO8D02hIMJKWdy9
ozuhTmbbWHiL1gU1iEDiCgj6bgmvmHeviL1LwF8IeoA2dgRIRxCG66YVnnqbGI8v7NlJ4ElgJEEm
RIkx/wgYLDpOxWZ4ReEpQkiiWg1rUoJRMAQjgGCTDeExgxa0oFsAhprHkxFCxCBfsGHNnYIOI6kJ
8rUheoJKgQrP6IXZ1lUL3g4Q5LCY44k6vQ0t9uBdw9x2AvSlOnzOVrAyQGPwdnSWkOXBDZjPUs1e
sfYtNYgT5QZCB2rhea03uBuU8mRWrn8jj9DFfdtmeo+BJC5OaEgISuzIwuYfcRBA3BesnKTlyO2u
scdrM7WtzuJDZAgXIJpRxnQsAW73zslrNfM33ZWvWBRKcl9asjLFDejDQsgxNBIDVAukDmJtNcgj
43wZDQmxWitIYHUIFN/ZF1NQuJ/PTzNM/SIHVLgOFUClYcjBEGIvhAWgMSIoJrBZ+HEWvyXdyz9c
+3r9hz1L/txt71uLJ9ZYHZfNAd3uJEtdiCUhvXQ1YZIPFYHmYerJ0pgKIsRggzRpkD8XCoEitxIU
rcMJIOAUs5XF+S9xyD6TyV6iDTG0xtdAyVGFoVlkHe73qU6dxWB2ucyg+ZXovY6oEHEkzcXzIHDI
5Bh9V1kpfkW7IxcusZH0juytAVFxQSZSHhAa0vA7n5zSYXgEjTkt788UcZzxUExSDcTWTUhtYZai
GCDdRZcEkmwanwZJrTERDRY2DB1zCSDgkgGl1LVmwmDEBaQXYmYJdLRljAmxXIBiaaBisYoxZSPP
+kN/uDsjbT2hgUU17/arUprITFOukJb5C7eYYye6fO3BeU9UAN4HyYtgJNKzeGKR0qvfqCLR3r7F
h9iJAZtsOYu7R/p4ENSLgWBYenahBUspsA49mVOMJs29sAmssIQaSVz6MUpylLkDWAq3EwYFgmJo
lYhMk4p8FPMRar1BXZCrFuhkl8338JSNZumLShhB95ChQfRF6EQicImGFMT9QP4IwOFxrU8IfeZ5
cT4dieIQEgzbQuJ3clBmErsV2rVaW4MyGs3UgvRpCjhe9q4Lg8cDR6VYCqp+466n+tZoZpj2q20A
GN1odsKGtihQNtNyyAY4gShTzJcKIlPpZsqYMJeNA0L8mnWOWCryobVcjn0mhDhmIg7X/xdyRThQ
kAoOMgw=

Reply via email to