+ int i;
+ const char **headers = resp->headers;
+ int name_len;
+
+ if (!headers || !headers[1])
+ return -1;
+
+ name_len = strlen (name);
+ if (start > 0)
+ i = start;
+ else
+ i = 1;
+
+ for (; headers[i + 1]; i++)
+ {
+ const char *b = headers[i];
+ const char *e = headers[i + 1];
+ if (e - b > name_len
+ && b[name_len] == ':'
+ && 0 == strncasecmp (b, name, name_len))
+ {
+ b += name_len + 1;
+ while (b < e && ISSPACE (*b))
+ ++b;
+ while (b < e && ISSPACE (e[-1]))
+ --e;
+ *begptr = b;
+ *endptr = e;
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* Find and retrieve the header named NAME in the request data. If
+ found, set *BEGPTR to its starting, and *ENDPTR to its ending
+ position, and return true. Otherwise return false.
+
+ This function is used as a building block for resp_header_copy
+ and resp_header_strdup. */
+
+static bool
+resp_header_get (const struct response *resp, const char *name,
+ const char **begptr, const char **endptr)
+{
+ int pos = resp_header_locate (resp, name, 0, begptr, endptr);
+ return pos != -1;
+}
+
+/* Copy the response header named NAME to buffer BUF, no longer than
+ BUFSIZE (BUFSIZE includes the terminating 0). If the header
+ exists, true is returned, false otherwise. If there should be no
+ limit on the size of the header, use resp_header_strdup instead.
+
+ If BUFSIZE is 0, no data is copied, but the boolean indication of
+ whether the header is present is still returned. */
+
+static bool
+resp_header_copy (const struct response *resp, const char *name,
+ char *buf, int bufsize)
+{
+ const char *b, *e;
+ if (!resp_header_get (resp, name, &b, &e))
+ return false;
+ if (bufsize)
+ {
+ int len = MIN (e - b, bufsize - 1);
+ memcpy (buf, b, len);
+ buf[len] = '\0';
+ }
+ return true;
+}
+
+/* Return the value of header named NAME in RESP, allocated with
+ malloc. If such a header does not exist in RESP, return NULL. */
+
+static char *
+resp_header_strdup (const struct response *resp, const char *name)
+{
+ const char *b, *e;
+ if (!resp_header_get (resp, name, &b, &e))
+ return NULL;
+ return strdupdelim (b, e);
+}
+
+/* Parse the HTTP status line, which is of format:
+
+ HTTP-Version SP Status-Code SP Reason-Phrase
+
+ The function returns the status-code, or -1 if the status line
+ appears malformed. The pointer to "reason-phrase" message is
+ returned in *MESSAGE. */
+
+static int
+resp_status (const struct response *resp, char **message)
+{
+ int status;
+ const char *p, *end;
+
+ if (!resp->headers)
+ {
+ /* For a HTTP/0.9 response, assume status 200. */
+ if (message)
+ *message = xstrdup (_("No headers, assuming HTTP/0.9"));
+ return 200;
+ }
+
+ p = resp->headers[0];
+ end = resp->headers[1];
+
+ if (!end)
+ return -1;
+
+ /* "HTTP" */
+ if (end - p < 4 || 0 != strncmp (p, "HTTP", 4))
+ return -1;
+ p += 4;
+
+ /* Match the HTTP version. This is optional because Gnutella
+ servers have been reported to not specify HTTP version. */
+ if (p < end && *p == '/')
+ {
+ ++p;
+ while (p < end && ISDIGIT (*p))
+ ++p;
+ if (p < end && *p == '.')
+ ++p;
+ while (p < end && ISDIGIT (*p))
+ ++p;
+ }
+
+ while (p < end && ISSPACE (*p))
+ ++p;
+ if (end - p < 3 || !ISDIGIT (p[0]) || !ISDIGIT (p[1]) || !ISDIGIT (p[2]))
+ return -1;
+
+ status = 100 * (p[0] - '0') + 10 * (p[1] - '0') + (p[2] - '0');
+ p += 3;
+
+ if (message)
+ {
+ while (p < end && ISSPACE (*p))
+ ++p;
+ while (p < end && ISSPACE (end[-1]))
+ --end;
+ *message = strdupdelim (p, end);
+ }
+
+ return status;
+}
+
+/* Release the resources used by RESP. */
+
+static void
+resp_free (struct response *resp)
+{
+ xfree_null (resp->headers);
+ xfree (resp);
+}
+
+/* Print the server response, line by line, omitting the trailing CRLF
+ from individual header lines, and prefixed with PREFIX. */
+
+static void
+print_server_response (const struct response *resp, const char *prefix)
+{
+ int i;
+ if (!resp->headers)
+ return;
+ for (i = 0; resp->headers[i + 1]; i++)
+ {
+ const char *b = resp->headers[i];
+ const char *e = resp->headers[i + 1];
+ /* Skip CRLF */
+ if (b < e && e[-1] == '\n')
+ --e;
+ if (b < e && e[-1] == '\r')
+ --e;
+ /* This is safe even on printfs with broken handling of "%.<n>s"
+ because resp->headers ends with \0. */
+ logprintf (LOG_VERBOSE, "%s%.*s\n", prefix, e - b, b);
+ }
+}
+
+/* Parse the `Content-Range' header and extract the information it
+ contains. Returns true if successful, false otherwise. */
+static bool
+parse_content_range (const char *hdr, wgint *first_byte_ptr,
+ wgint *last_byte_ptr, wgint *entity_length_ptr)
+{
+ wgint num;
+
+ /* Ancient versions of Netscape proxy server, presumably predating
+ rfc2068, sent out `Content-Range' without the "bytes"
+ specifier. */
+ if (0 == strncasecmp (hdr, "bytes", 5))