SH-4106 Significantly upgrade the HttpHeaders interface for SSB.

Mon, 15 Apr 2013 16:55:35 +0000

author
Monty Brandenberg <monty@lindenlab.com>
date
Mon, 15 Apr 2013 16:55:35 +0000
changeset 40683
5e594bc74503
parent 40682
a752aec20e0f
child 40684
f110aa675d5e

SH-4106 Significantly upgrade the HttpHeaders interface for SSB.
Header container moves from a vector of raw lines to a vector
of string pairs representing name/value pairs in headers. For
incoming headers, we normalize the name to lowercase and trim
it. Values are only left-trimmed. Outgoing headers are left
as-is. Simple find() method for the common case, forward and
reverse iterators for those few who need to do it themselves.
The HTTP status line (e.g. 'HTTP/1.1 200 Ok') is no longer treated
as a header to be returned to caller. Unit tests, as usual,
were a bear but they absolutely ensured outgoing HTTP header
conformance after the change. Grunt work paid off.

LLTextureFetch was also given a second options structure
for texture fetches. Same as the original but with header return
to caller requested. Baked textures should use this, the other
20,000 texture fetch requests should continue to use the original.

indra/llcorehttp/_httplibcurl.cpp file | annotate | diff | revisions
indra/llcorehttp/_httpoprequest.cpp file | annotate | diff | revisions
indra/llcorehttp/examples/http_texture_load.cpp file | annotate | diff | revisions
indra/llcorehttp/httpheaders.cpp file | annotate | diff | revisions
indra/llcorehttp/httpheaders.h file | annotate | diff | revisions
indra/llcorehttp/tests/test_httpheaders.hpp file | annotate | diff | revisions
indra/llcorehttp/tests/test_httprequest.hpp file | annotate | diff | revisions
indra/newview/lltexturefetch.cpp file | annotate | diff | revisions
indra/newview/lltexturefetch.h file | annotate | diff | revisions
     1.1 --- a/indra/llcorehttp/_httplibcurl.cpp	Wed Jun 19 13:55:54 2013 -0400
     1.2 +++ b/indra/llcorehttp/_httplibcurl.cpp	Mon Apr 15 16:55:35 2013 +0000
     1.3 @@ -4,7 +4,7 @@
     1.4   *
     1.5   * $LicenseInfo:firstyear=2012&license=viewerlgpl$
     1.6   * Second Life Viewer Source Code
     1.7 - * Copyright (C) 2012, Linden Research, Inc.
     1.8 + * Copyright (C) 2012-2013, Linden Research, Inc.
     1.9   *
    1.10   * This library is free software; you can redistribute it and/or
    1.11   * modify it under the terms of the GNU Lesser General Public
    1.12 @@ -359,12 +359,17 @@
    1.13  
    1.14  struct curl_slist * append_headers_to_slist(const HttpHeaders * headers, struct curl_slist * slist)
    1.15  {
    1.16 -	for (HttpHeaders::container_t::const_iterator it(headers->mHeaders.begin());
    1.17 -
    1.18 -		headers->mHeaders.end() != it;
    1.19 -		 ++it)
    1.20 +	const HttpHeaders::const_iterator end(headers->end());
    1.21 +	for (HttpHeaders::const_iterator it(headers->begin()); end != it; ++it)
    1.22  	{
    1.23 -		slist = curl_slist_append(slist, (*it).c_str());
    1.24 +		static const char sep[] = ": ";
    1.25 +		std::string header;
    1.26 +		header.reserve((*it).first.size() + (*it).second.size() + sizeof(sep));
    1.27 +		header.append((*it).first);
    1.28 +		header.append(sep);
    1.29 +		header.append((*it).second);
    1.30 +		
    1.31 +		slist = curl_slist_append(slist, header.c_str());
    1.32  	}
    1.33  	return slist;
    1.34  }
     2.1 --- a/indra/llcorehttp/_httpoprequest.cpp	Wed Jun 19 13:55:54 2013 -0400
     2.2 +++ b/indra/llcorehttp/_httpoprequest.cpp	Mon Apr 15 16:55:35 2013 +0000
     2.3 @@ -618,7 +618,8 @@
     2.4  
     2.5  	const size_t hdr_size(size * nmemb);
     2.6  	const char * hdr_data(static_cast<const char *>(data));		// Not null terminated
     2.7 -
     2.8 +	bool is_header(true);
     2.9 +	
    2.10  	if (hdr_size >= status_line_len && ! strncmp(status_line, hdr_data, status_line_len))
    2.11  	{
    2.12  		// One of possibly several status lines.  Reset what we know and start over
    2.13 @@ -629,8 +630,9 @@
    2.14  		op->mStatus = HttpStatus();
    2.15  		if (op->mReplyHeaders)
    2.16  		{
    2.17 -			op->mReplyHeaders->mHeaders.clear();
    2.18 +			op->mReplyHeaders->clear();
    2.19  		}
    2.20 +		is_header = false;
    2.21  	}
    2.22  
    2.23  	// Nothing in here wants a final CR/LF combination.  Remove
    2.24 @@ -645,18 +647,18 @@
    2.25  	}
    2.26  	
    2.27  	// Save header if caller wants them in the response
    2.28 -	if (op->mProcFlags & PF_SAVE_HEADERS)
    2.29 +	if (is_header && op->mProcFlags & PF_SAVE_HEADERS)
    2.30  	{
    2.31  		// Save headers in response
    2.32  		if (! op->mReplyHeaders)
    2.33  		{
    2.34  			op->mReplyHeaders = new HttpHeaders;
    2.35  		}
    2.36 -		op->mReplyHeaders->mHeaders.push_back(std::string(hdr_data, wanted_hdr_size));
    2.37 +		op->mReplyHeaders->appendNormal(hdr_data, wanted_hdr_size);
    2.38  	}
    2.39  
    2.40  	// Detect and parse 'Content-Range' headers
    2.41 -	if (op->mProcFlags & PF_SCAN_RANGE_HEADER)
    2.42 +	if (is_header && op->mProcFlags & PF_SCAN_RANGE_HEADER)
    2.43  	{
    2.44  		char hdr_buffer[128];			// Enough for a reasonable header
    2.45  		size_t frag_size((std::min)(wanted_hdr_size, sizeof(hdr_buffer) - 1));
     3.1 --- a/indra/llcorehttp/examples/http_texture_load.cpp	Wed Jun 19 13:55:54 2013 -0400
     3.2 +++ b/indra/llcorehttp/examples/http_texture_load.cpp	Mon Apr 15 16:55:35 2013 +0000
     3.3 @@ -4,7 +4,7 @@
     3.4   *
     3.5   * $LicenseInfo:firstyear=2012&license=viewerlgpl$
     3.6   * Second Life Viewer Source Code
     3.7 - * Copyright (C) 2012, Linden Research, Inc.
     3.8 + * Copyright (C) 2012-2013, Linden Research, Inc.
     3.9   * 
    3.10   * This library is free software; you can redistribute it and/or
    3.11   * modify it under the terms of the GNU Lesser General Public
    3.12 @@ -328,7 +328,7 @@
    3.13  	mTextures.reserve(30000);
    3.14  
    3.15  	mHeaders = new LLCore::HttpHeaders;
    3.16 -	mHeaders->mHeaders.push_back("Accept: image/x-j2c");
    3.17 +	mHeaders->append("Accept", "image/x-j2c");
    3.18  }
    3.19  
    3.20  
     4.1 --- a/indra/llcorehttp/httpheaders.cpp	Wed Jun 19 13:55:54 2013 -0400
     4.2 +++ b/indra/llcorehttp/httpheaders.cpp	Mon Apr 15 16:55:35 2013 +0000
     4.3 @@ -4,7 +4,7 @@
     4.4   *
     4.5   * $LicenseInfo:firstyear=2012&license=viewerlgpl$
     4.6   * Second Life Viewer Source Code
     4.7 - * Copyright (C) 2012, Linden Research, Inc.
     4.8 + * Copyright (C) 2012-2013, Linden Research, Inc.
     4.9   *
    4.10   * This library is free software; you can redistribute it and/or
    4.11   * modify it under the terms of the GNU Lesser General Public
    4.12 @@ -26,6 +26,8 @@
    4.13  
    4.14  #include "httpheaders.h"
    4.15  
    4.16 +#include "llstring.h"
    4.17 +
    4.18  
    4.19  namespace LLCore
    4.20  {
    4.21 @@ -40,5 +42,142 @@
    4.22  {}
    4.23  
    4.24  
    4.25 +void
    4.26 +HttpHeaders::clear()
    4.27 +{
    4.28 +	mHeaders.clear();
    4.29 +}
    4.30 +
    4.31 +
    4.32 +void HttpHeaders::append(const std::string & name, const std::string & value)
    4.33 +{
    4.34 +	mHeaders.push_back(value_type(name, value));
    4.35 +}
    4.36 +
    4.37 +
    4.38 +void HttpHeaders::append(const char * name, const char * value)
    4.39 +{
    4.40 +	mHeaders.push_back(value_type(name, value));
    4.41 +}
    4.42 +
    4.43 +
    4.44 +void HttpHeaders::appendNormal(const char * header, size_t size)
    4.45 +{
    4.46 +	std::string name;
    4.47 +	std::string value;
    4.48 +
    4.49 +	int col_pos(0);
    4.50 +	for (; col_pos < size; ++col_pos)
    4.51 +	{
    4.52 +		if (':' == header[col_pos])
    4.53 +			break;
    4.54 +	}
    4.55 +	
    4.56 +	if (col_pos < size)
    4.57 +	{
    4.58 +		// Looks like a header, split it and normalize.
    4.59 +		// Name is everything before the colon, may be zero-length.
    4.60 +		name.assign(header, col_pos);
    4.61 +
    4.62 +		// Value is everything after the colon, may also be zero-length.
    4.63 +		const size_t val_len(size - col_pos - 1);
    4.64 +		if (val_len)
    4.65 +		{
    4.66 +			value.assign(header + col_pos + 1, val_len);
    4.67 +		}
    4.68 +
    4.69 +		// Clean the strings
    4.70 +		LLStringUtil::toLower(name);
    4.71 +		LLStringUtil::trim(name);
    4.72 +		LLStringUtil::trimHead(value);
    4.73 +	}
    4.74 +	else
    4.75 +	{
    4.76 +		// Uncertain what this is, we'll pack it as
    4.77 +		// a name without a value.  Won't clean as we don't
    4.78 +		// know what it is...
    4.79 +		name.assign(header, size);
    4.80 +	}
    4.81 +
    4.82 +	mHeaders.push_back(value_type(name, value));
    4.83 +}
    4.84 +
    4.85 +
    4.86 +// Find from end to simulate a tradition of using single-valued
    4.87 +// std::map for this in the past.
    4.88 +const std::string * HttpHeaders::find(const char * name) const
    4.89 +{
    4.90 +	const_reverse_iterator iend(rend());
    4.91 +	for (const_reverse_iterator iter(rbegin()); iend != iter; ++iter)
    4.92 +	{
    4.93 +		if ((*iter).first == name)
    4.94 +		{
    4.95 +			return &(*iter).second;
    4.96 +		}
    4.97 +	}
    4.98 +	return NULL;
    4.99 +}
   4.100 +
   4.101 +
   4.102 +// Standard Iterators
   4.103 +HttpHeaders::iterator HttpHeaders::begin()
   4.104 +{
   4.105 +	return mHeaders.begin();
   4.106 +}
   4.107 +
   4.108 +
   4.109 +HttpHeaders::const_iterator HttpHeaders::begin() const
   4.110 +{
   4.111 +	return mHeaders.begin();
   4.112 +}
   4.113 +
   4.114 +
   4.115 +HttpHeaders::iterator HttpHeaders::end()
   4.116 +{
   4.117 +	return mHeaders.end();
   4.118 +}
   4.119 +
   4.120 +
   4.121 +HttpHeaders::const_iterator HttpHeaders::end() const
   4.122 +{
   4.123 +	return mHeaders.end();
   4.124 +}
   4.125 +
   4.126 +
   4.127 +// Standard Reverse Iterators
   4.128 +HttpHeaders::reverse_iterator HttpHeaders::rbegin()
   4.129 +{
   4.130 +	return mHeaders.rbegin();
   4.131 +}
   4.132 +
   4.133 +
   4.134 +HttpHeaders::const_reverse_iterator HttpHeaders::rbegin() const
   4.135 +{
   4.136 +	return mHeaders.rbegin();
   4.137 +}
   4.138 +
   4.139 +
   4.140 +HttpHeaders::reverse_iterator HttpHeaders::rend()
   4.141 +{
   4.142 +	return mHeaders.rend();
   4.143 +}
   4.144 +
   4.145 +
   4.146 +HttpHeaders::const_reverse_iterator HttpHeaders::rend() const
   4.147 +{
   4.148 +	return mHeaders.rend();
   4.149 +}
   4.150 +
   4.151 +
   4.152 +// Return the raw container to the caller.
   4.153 +//
   4.154 +// To be used FOR UNIT TESTS ONLY.
   4.155 +//
   4.156 +HttpHeaders::container_t & HttpHeaders::getContainerTESTONLY()
   4.157 +{
   4.158 +	return mHeaders;
   4.159 +}
   4.160 +
   4.161 +
   4.162  }   // end namespace LLCore
   4.163  
     5.1 --- a/indra/llcorehttp/httpheaders.h	Wed Jun 19 13:55:54 2013 -0400
     5.2 +++ b/indra/llcorehttp/httpheaders.h	Mon Apr 15 16:55:35 2013 +0000
     5.3 @@ -4,7 +4,7 @@
     5.4   *
     5.5   * $LicenseInfo:firstyear=2012&license=viewerlgpl$
     5.6   * Second Life Viewer Source Code
     5.7 - * Copyright (C) 2012, Linden Research, Inc.
     5.8 + * Copyright (C) 2012-2013, Linden Research, Inc.
     5.9   *
    5.10   * This library is free software; you can redistribute it and/or
    5.11   * modify it under the terms of the GNU Lesser General Public
    5.12 @@ -43,13 +43,26 @@
    5.13  /// caller has asked that headers be returned (not the default
    5.14  /// option).
    5.15  ///
    5.16 -/// @note
    5.17 -/// This is a minimally-functional placeholder at the moment
    5.18 -/// to fill out the class hierarchy.  The final class will be
    5.19 -/// something else, probably more pair-oriented.  It's also
    5.20 -/// an area where shared values are desirable so refcounting is
    5.21 -/// already specced and a copy-on-write scheme imagined.
    5.22 -/// Expect changes here.
    5.23 +/// Class is mostly a thin wrapper around a vector of pairs
    5.24 +/// of strings.  Methods provided are few and intended to
    5.25 +/// reflect actual use patterns.  These include:
    5.26 +/// - Clearing the list
    5.27 +/// - Appending a name/value pair to the vector
    5.28 +/// - Processing a raw byte string into a normalized name/value
    5.29 +///   pair and appending the result.
    5.30 +/// - Simple case-sensitive find-last-by-name search
    5.31 +/// - Forward and reverse iterators over all pairs
    5.32 +///
    5.33 +/// Container is ordered and multi-valued.  Headers are
    5.34 +/// written in the order in which they are appended and
    5.35 +/// are stored in the order in which they're received from
    5.36 +/// the wire.  The same header may appear two or more times
    5.37 +/// in any container.  Searches using the simple find()
    5.38 +/// interface will find only the last occurrence (somewhat
    5.39 +/// simulates the use of std::map).  Fuller searches require
    5.40 +/// the use of an iterator.  Headers received from the wire
    5.41 +/// are only returned from the last request when redirections
    5.42 +/// are involved.
    5.43  ///
    5.44  /// Threading:  Not intrinsically thread-safe.  It *is* expected
    5.45  /// that callers will build these objects and then share them
    5.46 @@ -64,6 +77,16 @@
    5.47  class HttpHeaders : public LLCoreInt::RefCounted
    5.48  {
    5.49  public:
    5.50 +	typedef std::pair<std::string, std::string> header_t;
    5.51 +	typedef std::vector<header_t> container_t;
    5.52 +	typedef container_t::iterator iterator;
    5.53 +	typedef container_t::const_iterator const_iterator;
    5.54 +	typedef container_t::reverse_iterator reverse_iterator;
    5.55 +	typedef container_t::const_reverse_iterator const_reverse_iterator;
    5.56 +	typedef container_t::value_type value_type;
    5.57 +	typedef container_t::size_type size_type;
    5.58 +
    5.59 +public:
    5.60  	/// @post In addition to the instance, caller has a refcount
    5.61  	/// to the instance.  A call to @see release() will destroy
    5.62  	/// the instance.
    5.63 @@ -76,7 +99,78 @@
    5.64  	void operator=(const HttpHeaders &);		// Not defined
    5.65  
    5.66  public:
    5.67 -	typedef std::vector<std::string> container_t;
    5.68 +	// Empty the list of headers.
    5.69 +	void clear();
    5.70 +
    5.71 +	// Append a name/value pair supplied as either std::strings
    5.72 +	// or NUL-terminated char * to the header list.  No normalization
    5.73 +	// is performed on the strings.  No conformance test is
    5.74 +	// performed (names may contain spaces, colons, etc.).
    5.75 +	//
    5.76 +	void append(const std::string & name, const std::string & value);
    5.77 +	void append(const char * name, const char * value);
    5.78 +
    5.79 +	// Extract a name/value pair from a raw byte array using
    5.80 +	// the first colon character as a separator.  Input string
    5.81 +	// does not need to be NUL-terminated.  Resulting name/value
    5.82 +	// pair is appended to the header list.
    5.83 +	//
    5.84 +	// Normalization is performed on the name/value pair as
    5.85 +	// follows:
    5.86 +	// - name is lower-cased according to mostly ASCII rules
    5.87 +	// - name is left- and right-trimmed of spaces and tabs
    5.88 +	// - value is left-trimmed of spaces and tabs
    5.89 +	// - either or both of name and value may be zero-length
    5.90 +	//
    5.91 +	// By convention, headers read from the wire will be normalized
    5.92 +	// in this fashion prior to delivery to any HttpHandler code.
    5.93 +	// Headers to be written to the wire are left as appended to
    5.94 +	// the list.
    5.95 +	void appendNormal(const char * header, size_t size);
    5.96 +
    5.97 +	// Perform a simple, case-sensitive search of the header list
    5.98 +	// returning a pointer to the value of the last matching header
    5.99 +	// in the header list.  If none is found, a NULL pointer is returned.
   5.100 +	//
   5.101 +	// Any pointer returned references objects in the container itself
   5.102 +	// and will have the same lifetime as this class.  If you want
   5.103 +	// the value beyond the lifetime of this instance, make a copy.
   5.104 +	//
   5.105 +	// @arg		name	C-style string giving the name of a header
   5.106 +	//					to search.  The comparison is case-sensitive
   5.107 +	//					though list entries may have been normalized
   5.108 +	//					to lower-case.
   5.109 +	//
   5.110 +	// @return			NULL if the header wasn't found otherwise
   5.111 +	//					a pointer to a std::string in the container.
   5.112 +	//					Pointer is valid only for the lifetime of
   5.113 +	//					the container or until container is modifed.
   5.114 +	//
   5.115 +	const std::string * find(const char * name) const;
   5.116 +
   5.117 +	// Count of headers currently in the list.
   5.118 +	size_type size() const
   5.119 +		{
   5.120 +			return mHeaders.size();
   5.121 +		}
   5.122 +
   5.123 +	// Standard std::vector-based forward iterators.
   5.124 +	iterator begin();
   5.125 +	const_iterator begin() const;
   5.126 +	iterator end();
   5.127 +	const_iterator end() const;
   5.128 +
   5.129 +	// Standard std::vector-based reverse iterators.
   5.130 +	reverse_iterator rbegin();
   5.131 +	const_reverse_iterator rbegin() const;
   5.132 +	reverse_iterator rend();
   5.133 +	const_reverse_iterator rend() const;
   5.134 +
   5.135 +public:
   5.136 +	// For unit tests only - not a public API
   5.137 +	container_t &		getContainerTESTONLY();
   5.138 +	
   5.139 +protected:
   5.140  	container_t			mHeaders;
   5.141  	
   5.142  }; // end class HttpHeaders
     6.1 --- a/indra/llcorehttp/tests/test_httpheaders.hpp	Wed Jun 19 13:55:54 2013 -0400
     6.2 +++ b/indra/llcorehttp/tests/test_httpheaders.hpp	Mon Apr 15 16:55:35 2013 +0000
     6.3 @@ -4,7 +4,7 @@
     6.4   *
     6.5   * $LicenseInfo:firstyear=2012&license=viewerlgpl$
     6.6   * Second Life Viewer Source Code
     6.7 - * Copyright (C) 2012, Linden Research, Inc.
     6.8 + * Copyright (C) 2012-2013, Linden Research, Inc.
     6.9   *
    6.10   * This library is free software; you can redistribute it and/or
    6.11   * modify it under the terms of the GNU Lesser General Public
    6.12 @@ -36,7 +36,6 @@
    6.13  using namespace LLCoreInt;
    6.14  
    6.15  
    6.16 -
    6.17  namespace tut
    6.18  {
    6.19  
    6.20 @@ -63,7 +62,7 @@
    6.21  	HttpHeaders * headers = new HttpHeaders();
    6.22  	ensure("One ref on construction of HttpHeaders", headers->getRefCount() == 1);
    6.23  	ensure("Memory being used", mMemTotal < GetMemTotal());
    6.24 -	ensure("Nothing in headers", 0 == headers->mHeaders.size());
    6.25 +	ensure("Nothing in headers", 0 == headers->size());
    6.26  
    6.27  	// release the implicit reference, causing the object to be released
    6.28  	headers->release();
    6.29 @@ -85,14 +84,340 @@
    6.30  	
    6.31  	{
    6.32  		// Append a few strings
    6.33 -		std::string str1("Pragma:");
    6.34 -		headers->mHeaders.push_back(str1);
    6.35 -		std::string str2("Accept: application/json");
    6.36 -		headers->mHeaders.push_back(str2);
    6.37 +		std::string str1n("Pragma");
    6.38 +		std::string str1v("");
    6.39 +		headers->append(str1n, str1v);
    6.40 +		std::string str2n("Accept");
    6.41 +		std::string str2v("application/json");
    6.42 +		headers->append(str2n, str2v);
    6.43  	
    6.44 -		ensure("Headers retained", 2 == headers->mHeaders.size());
    6.45 -		ensure("First is first", headers->mHeaders[0] == str1);
    6.46 -		ensure("Second is second", headers->mHeaders[1] == str2);
    6.47 +		ensure("Headers retained", 2 == headers->size());
    6.48 +		HttpHeaders::container_t & c(headers->getContainerTESTONLY());
    6.49 +		
    6.50 +		ensure("First name is first name", c[0].first == str1n);
    6.51 +		ensure("First value is first value", c[0].second == str1v);
    6.52 +		ensure("Second name is second name", c[1].first == str2n);
    6.53 +		ensure("Second value is second value", c[1].second == str2v);
    6.54 +	}
    6.55 +	
    6.56 +	// release the implicit reference, causing the object to be released
    6.57 +	headers->release();
    6.58 +
    6.59 +	// make sure we didn't leak any memory
    6.60 +	ensure(mMemTotal == GetMemTotal());
    6.61 +}
    6.62 +
    6.63 +template <> template <>
    6.64 +void HttpHeadersTestObjectType::test<3>()
    6.65 +{
    6.66 +	set_test_name("HttpHeaders basic find");
    6.67 +
    6.68 +	// record the total amount of dynamically allocated memory
    6.69 +	mMemTotal = GetMemTotal();
    6.70 +
    6.71 +	// create a new ref counted object with an implicit reference
    6.72 +	HttpHeaders * headers = new HttpHeaders();
    6.73 +	
    6.74 +	{
    6.75 +		// Append a few strings
    6.76 +		std::string str1n("Uno");
    6.77 +		std::string str1v("1");
    6.78 +		headers->append(str1n, str1v);
    6.79 +		std::string str2n("doS");
    6.80 +		std::string str2v("2-2-2-2");
    6.81 +		headers->append(str2n, str2v);
    6.82 +		std::string str3n("TRES");
    6.83 +		std::string str3v("trois gymnopedie");
    6.84 +		headers->append(str3n, str3v);
    6.85 +	
    6.86 +		ensure("Headers retained", 3 == headers->size());
    6.87 +
    6.88 +		const std::string * result(NULL);
    6.89 +
    6.90 +		// Find a header
    6.91 +		result = headers->find("TRES");
    6.92 +		ensure("Found the last item", result != NULL);
    6.93 +		ensure("Last item is a nice", result != NULL && str3v == *result);
    6.94 +
    6.95 +		// appends above are raw and find is case sensitive
    6.96 +		result = headers->find("TReS");
    6.97 +		ensure("Last item not found due to case", result == NULL);
    6.98 +
    6.99 +		result = headers->find("TRE");
   6.100 +		ensure("Last item not found due to prefixing (1)", result == NULL);
   6.101 +
   6.102 +		result = headers->find("TRESS");
   6.103 +		ensure("Last item not found due to prefixing (2)", result == NULL);
   6.104 +	}
   6.105 +	
   6.106 +	// release the implicit reference, causing the object to be released
   6.107 +	headers->release();
   6.108 +
   6.109 +	// make sure we didn't leak any memory
   6.110 +	ensure(mMemTotal == GetMemTotal());
   6.111 +}
   6.112 +
   6.113 +template <> template <>
   6.114 +void HttpHeadersTestObjectType::test<4>()
   6.115 +{
   6.116 +	set_test_name("HttpHeaders normalized header entry");
   6.117 +
   6.118 +	// record the total amount of dynamically allocated memory
   6.119 +	mMemTotal = GetMemTotal();
   6.120 +
   6.121 +	// create a new ref counted object with an implicit reference
   6.122 +	HttpHeaders * headers = new HttpHeaders();
   6.123 +	
   6.124 +	{
   6.125 +		static char line1[] = " AcCePT : image/yourfacehere";
   6.126 +		static char line1v[] = "image/yourfacehere";
   6.127 +		headers->appendNormal(line1, sizeof(line1) - 1);
   6.128 +		
   6.129 +		ensure("First append worked in some fashion", 1 == headers->size());
   6.130 +
   6.131 +		const std::string * result(NULL);
   6.132 +
   6.133 +		// Find a header
   6.134 +		result = headers->find("accept");
   6.135 +		ensure("Found 'accept'", result != NULL);
   6.136 +		ensure("accept value has face", result != NULL && *result == line1v);
   6.137 +
   6.138 +		// Left-clean on value
   6.139 +		static char line2[] = " next : \t\tlinejunk \t";
   6.140 +		headers->appendNormal(line2, sizeof(line2) - 1);
   6.141 +		ensure("Second append worked", 2 == headers->size());
   6.142 +		result = headers->find("next");
   6.143 +		ensure("Found 'next'", result != NULL);
   6.144 +		ensure("next value is left-clean", result != NULL &&
   6.145 +			   *result == "linejunk \t");
   6.146 +
   6.147 +		// First value unmolested
   6.148 +		result = headers->find("accept");
   6.149 +		ensure("Found 'accept' again", result != NULL);
   6.150 +		ensure("accept value has face", result != NULL && *result == line1v);
   6.151 +
   6.152 +		// Colons in value are okay
   6.153 +		static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
   6.154 +		static char line3v[] = ":plop:-neuf-=vleem=";
   6.155 +		headers->appendNormal(line3, sizeof(line3) - 1);
   6.156 +		ensure("Third append worked", 3 == headers->size());
   6.157 +		result = headers->find("fancy-pants");
   6.158 +		ensure("Found 'fancy-pants'", result != NULL);
   6.159 +		ensure("fancy-pants value has colons", result != NULL && *result == line3v);
   6.160 +
   6.161 +		// Zero-length value
   6.162 +		static char line4[] = "all-talk-no-walk:";
   6.163 +		headers->appendNormal(line4, sizeof(line4) - 1);
   6.164 +		ensure("Fourth append worked", 4 == headers->size());
   6.165 +		result = headers->find("all-talk-no-walk");
   6.166 +		ensure("Found 'all-talk'", result != NULL);
   6.167 +		ensure("al-talk value is zero-length", result != NULL && result->size() == 0);
   6.168 +
   6.169 +		// Zero-length name
   6.170 +		static char line5[] = ":all-talk-no-walk";
   6.171 +		static char line5v[] = "all-talk-no-walk";
   6.172 +		headers->appendNormal(line5, sizeof(line5) - 1);
   6.173 +		ensure("Fifth append worked", 5 == headers->size());
   6.174 +		result = headers->find("");
   6.175 +		ensure("Found no-name", result != NULL);
   6.176 +		ensure("no-name value is something", result != NULL && *result == line5v);
   6.177 +
   6.178 +		// Lone colon is still something
   6.179 +		headers->clear();
   6.180 +		static char line6[] = "  :";
   6.181 +		headers->appendNormal(line6, sizeof(line6) - 1);
   6.182 +		ensure("Sixth append worked", 1 == headers->size());
   6.183 +		result = headers->find("");
   6.184 +		ensure("Found 2nd no-name", result != NULL);
   6.185 +		ensure("2nd no-name value is nothing", result != NULL && result->size() == 0);
   6.186 +
   6.187 +		// Line without colons is taken as-is and unstripped in name
   6.188 +		static char line7[] = " \toskdgioasdghaosdghoowg28342908tg8902hg0hwedfhqew890v7qh0wdebv78q0wdevbhq>?M>BNM<ZV>?NZ? \t";
   6.189 +		headers->appendNormal(line7, sizeof(line7) - 1);
   6.190 +		ensure("Seventh append worked", 2 == headers->size());
   6.191 +		result = headers->find(line7);
   6.192 +		ensure("Found whatsit line", result != NULL);
   6.193 +		ensure("Whatsit line has no value", result != NULL && result->size() == 0);
   6.194 +
   6.195 +		// Normaling interface heeds the byte count, doesn't look for NUL-terminator
   6.196 +		static char line8[] = "binary:ignorestuffontheendofthis";
   6.197 +		headers->appendNormal(line8, 13);
   6.198 +		ensure("Eighth append worked", 3 == headers->size());
   6.199 +		result = headers->find("binary");
   6.200 +		ensure("Found 'binary'", result != NULL);
   6.201 +		ensure("binary value was limited to 'ignore'", result != NULL &&
   6.202 +			   *result == "ignore");
   6.203 +
   6.204 +	}
   6.205 +	
   6.206 +	// release the implicit reference, causing the object to be released
   6.207 +	headers->release();
   6.208 +
   6.209 +	// make sure we didn't leak any memory
   6.210 +	ensure(mMemTotal == GetMemTotal());
   6.211 +}
   6.212 +
   6.213 +// Verify forward iterator finds everything as expected
   6.214 +template <> template <>
   6.215 +void HttpHeadersTestObjectType::test<5>()
   6.216 +{
   6.217 +	set_test_name("HttpHeaders iterator tests");
   6.218 +
   6.219 +	// record the total amount of dynamically allocated memory
   6.220 +	mMemTotal = GetMemTotal();
   6.221 +
   6.222 +	// create a new ref counted object with an implicit reference
   6.223 +	HttpHeaders * headers = new HttpHeaders();
   6.224 +
   6.225 +	HttpHeaders::iterator end(headers->end()), begin(headers->begin());
   6.226 +	ensure("Empty container has equal begin/end const iterators", end == begin);
   6.227 +	HttpHeaders::const_iterator cend(headers->end()), cbegin(headers->begin());
   6.228 +	ensure("Empty container has equal rbegin/rend const iterators", cend == cbegin);
   6.229 +
   6.230 +	ensure("Empty container has equal begin/end iterators", headers->end() == headers->begin());
   6.231 +	
   6.232 +	{
   6.233 +		static char line1[] = " AcCePT : image/yourfacehere";
   6.234 +		static char line1v[] = "image/yourfacehere";
   6.235 +		headers->appendNormal(line1, sizeof(line1) - 1);
   6.236 +
   6.237 +		static char line2[] = " next : \t\tlinejunk \t";
   6.238 +		static char line2v[] = "linejunk \t";
   6.239 +		headers->appendNormal(line2, sizeof(line2) - 1);
   6.240 +
   6.241 +		static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
   6.242 +		static char line3v[] = ":plop:-neuf-=vleem=";
   6.243 +		headers->appendNormal(line3, sizeof(line3) - 1);
   6.244 +
   6.245 +		static char line4[] = "all-talk-no-walk:";
   6.246 +		static char line4v[] = "";
   6.247 +		headers->appendNormal(line4, sizeof(line4) - 1);
   6.248 +
   6.249 +		static char line5[] = ":all-talk-no-walk";
   6.250 +		static char line5v[] = "all-talk-no-walk";
   6.251 +		headers->appendNormal(line5, sizeof(line5) - 1);
   6.252 +
   6.253 +		static char line6[] = "  :";
   6.254 +		static char line6v[] = "";
   6.255 +		headers->appendNormal(line6, sizeof(line6) - 1);
   6.256 +
   6.257 +		ensure("All entries accounted for", 6 == headers->size());
   6.258 +
   6.259 +		static char * values[] = {
   6.260 +			line1v,
   6.261 +			line2v,
   6.262 +			line3v,
   6.263 +			line4v,
   6.264 +			line5v,
   6.265 +			line6v
   6.266 +		};
   6.267 +			
   6.268 +		int i(0);
   6.269 +		HttpHeaders::const_iterator cend(headers->end());
   6.270 +		for (HttpHeaders::const_iterator it(headers->begin());
   6.271 +			 cend != it;
   6.272 +			 ++it, ++i)
   6.273 +		{
   6.274 +			std::ostringstream str;
   6.275 +			str << "Const Iterator value # " << i << " was " << values[i];
   6.276 +			ensure(str.str(), (*it).second == values[i]);
   6.277 +		}
   6.278 +
   6.279 +		// Rewind, do non-consts
   6.280 +		i = 0;
   6.281 +		HttpHeaders::iterator end(headers->end());
   6.282 +		for (HttpHeaders::iterator it(headers->begin());
   6.283 +			 end != it;
   6.284 +			 ++it, ++i)
   6.285 +		{
   6.286 +			std::ostringstream str;
   6.287 +			str << "Const Iterator value # " << i << " was " << values[i];
   6.288 +			ensure(str.str(), (*it).second == values[i]);
   6.289 +		}
   6.290 +	}
   6.291 +	
   6.292 +	// release the implicit reference, causing the object to be released
   6.293 +	headers->release();
   6.294 +
   6.295 +	// make sure we didn't leak any memory
   6.296 +	ensure(mMemTotal == GetMemTotal());
   6.297 +}
   6.298 +
   6.299 +// Reverse iterators find everything as expected
   6.300 +template <> template <>
   6.301 +void HttpHeadersTestObjectType::test<6>()
   6.302 +{
   6.303 +	set_test_name("HttpHeaders reverse iterator tests");
   6.304 +
   6.305 +	// record the total amount of dynamically allocated memory
   6.306 +	mMemTotal = GetMemTotal();
   6.307 +
   6.308 +	// create a new ref counted object with an implicit reference
   6.309 +	HttpHeaders * headers = new HttpHeaders();
   6.310 +
   6.311 +	HttpHeaders::reverse_iterator rend(headers->rend()), rbegin(headers->rbegin());
   6.312 +	ensure("Empty container has equal rbegin/rend const iterators", rend == rbegin);
   6.313 +	HttpHeaders::const_reverse_iterator crend(headers->rend()), crbegin(headers->rbegin());
   6.314 +	ensure("Empty container has equal rbegin/rend const iterators", crend == crbegin);
   6.315 +	
   6.316 +	{
   6.317 +		static char line1[] = " AcCePT : image/yourfacehere";
   6.318 +		static char line1v[] = "image/yourfacehere";
   6.319 +		headers->appendNormal(line1, sizeof(line1) - 1);
   6.320 +
   6.321 +		static char line2[] = " next : \t\tlinejunk \t";
   6.322 +		static char line2v[] = "linejunk \t";
   6.323 +		headers->appendNormal(line2, sizeof(line2) - 1);
   6.324 +
   6.325 +		static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
   6.326 +		static char line3v[] = ":plop:-neuf-=vleem=";
   6.327 +		headers->appendNormal(line3, sizeof(line3) - 1);
   6.328 +
   6.329 +		static char line4[] = "all-talk-no-walk:";
   6.330 +		static char line4v[] = "";
   6.331 +		headers->appendNormal(line4, sizeof(line4) - 1);
   6.332 +
   6.333 +		static char line5[] = ":all-talk-no-walk";
   6.334 +		static char line5v[] = "all-talk-no-walk";
   6.335 +		headers->appendNormal(line5, sizeof(line5) - 1);
   6.336 +
   6.337 +		static char line6[] = "  :";
   6.338 +		static char line6v[] = "";
   6.339 +		headers->appendNormal(line6, sizeof(line6) - 1);
   6.340 +
   6.341 +		ensure("All entries accounted for", 6 == headers->size());
   6.342 +
   6.343 +		static char * values[] = {
   6.344 +			line6v,
   6.345 +			line5v,
   6.346 +			line4v,
   6.347 +			line3v,
   6.348 +			line2v,
   6.349 +			line1v
   6.350 +		};
   6.351 +			
   6.352 +		int i(0);
   6.353 +		HttpHeaders::const_reverse_iterator cend(headers->rend());
   6.354 +		for (HttpHeaders::const_reverse_iterator it(headers->rbegin());
   6.355 +			 cend != it;
   6.356 +			 ++it, ++i)
   6.357 +		{
   6.358 +			std::ostringstream str;
   6.359 +			str << "Const Iterator value # " << i << " was " << values[i];
   6.360 +			ensure(str.str(), (*it).second == values[i]);
   6.361 +		}
   6.362 +
   6.363 +		// Rewind, do non-consts
   6.364 +		i = 0;
   6.365 +		HttpHeaders::reverse_iterator end(headers->rend());
   6.366 +		for (HttpHeaders::reverse_iterator it(headers->rbegin());
   6.367 +			 end != it;
   6.368 +			 ++it, ++i)
   6.369 +		{
   6.370 +			std::ostringstream str;
   6.371 +			str << "Iterator value # " << i << " was " << values[i];
   6.372 +			ensure(str.str(), (*it).second == values[i]);
   6.373 +		}
   6.374  	}
   6.375  	
   6.376  	// release the implicit reference, causing the object to be released
     7.1 --- a/indra/llcorehttp/tests/test_httprequest.hpp	Wed Jun 19 13:55:54 2013 -0400
     7.2 +++ b/indra/llcorehttp/tests/test_httprequest.hpp	Mon Apr 15 16:55:35 2013 +0000
     7.3 @@ -4,7 +4,7 @@
     7.4   *
     7.5   * $LicenseInfo:firstyear=2012&license=viewerlgpl$
     7.6   * Second Life Viewer Source Code
     7.7 - * Copyright (C) 2012, Linden Research, Inc.
     7.8 + * Copyright (C) 2012-2013, Linden Research, Inc.
     7.9   *
    7.10   * This library is free software; you can redistribute it and/or
    7.11   * modify it under the terms of the GNU Lesser General Public
    7.12 @@ -60,6 +60,8 @@
    7.13  namespace tut
    7.14  {
    7.15  
    7.16 +typedef std::vector<std::pair<boost::regex, boost::regex> > regex_container_t;
    7.17 +
    7.18  struct HttpRequestTestData
    7.19  {
    7.20  	// the test objects inherit from this so the member functions and variables
    7.21 @@ -109,11 +111,17 @@
    7.22  					for (int i(0); i < mHeadersRequired.size(); ++i)
    7.23  					{
    7.24  						bool found = false;
    7.25 -						for (HttpHeaders::container_t::const_iterator iter(header->mHeaders.begin());
    7.26 -							 header->mHeaders.end() != iter;
    7.27 +						for (HttpHeaders::const_iterator iter(header->begin());
    7.28 +							 header->end() != iter;
    7.29  							 ++iter)
    7.30  						{
    7.31 -							if (boost::regex_match(*iter, mHeadersRequired[i]))
    7.32 +							// std::cerr << "Header: " << (*iter).first
    7.33 +							//		  << ": " << (*iter).second << std::endl;
    7.34 +							
    7.35 +							if (boost::regex_match((*iter).first,
    7.36 +												   mHeadersRequired[i].first) &&
    7.37 +								boost::regex_match((*iter).second,
    7.38 +												   mHeadersRequired[i].second))
    7.39  							{
    7.40  								found = true;
    7.41  								break;
    7.42 @@ -129,11 +137,14 @@
    7.43  				{
    7.44  					for (int i(0); i < mHeadersDisallowed.size(); ++i)
    7.45  					{
    7.46 -						for (HttpHeaders::container_t::const_iterator iter(header->mHeaders.begin());
    7.47 -							 header->mHeaders.end() != iter;
    7.48 +						for (HttpHeaders::const_iterator iter(header->begin());
    7.49 +							 header->end() != iter;
    7.50  							 ++iter)
    7.51  						{
    7.52 -							if (boost::regex_match(*iter, mHeadersDisallowed[i]))
    7.53 +							if (boost::regex_match((*iter).first,
    7.54 +												   mHeadersDisallowed[i].first) &&
    7.55 +								boost::regex_match((*iter).second,
    7.56 +												   mHeadersDisallowed[i].second))
    7.57  							{
    7.58  								std::ostringstream str;
    7.59  								str << "Disallowed header # " << i << " not found in response";
    7.60 @@ -159,8 +170,8 @@
    7.61  	std::string mName;
    7.62  	HttpHandle mExpectHandle;
    7.63  	std::string mCheckContentType;
    7.64 -	std::vector<boost::regex> mHeadersRequired;
    7.65 -	std::vector<boost::regex> mHeadersDisallowed;
    7.66 +	regex_container_t mHeadersRequired;
    7.67 +	regex_container_t mHeadersDisallowed;
    7.68  };
    7.69  
    7.70  typedef test_group<HttpRequestTestData> HttpRequestTestGroupType;
    7.71 @@ -1335,7 +1346,9 @@
    7.72  		
    7.73  		// Issue a GET that succeeds
    7.74  		mStatus = HttpStatus(200);
    7.75 -		handler.mHeadersRequired.push_back(boost::regex("\\W*X-LL-Special:.*", boost::regex::icase));
    7.76 +		handler.mHeadersRequired.push_back(
    7.77 +			regex_container_t::value_type(boost::regex("X-LL-Special", boost::regex::icase),
    7.78 +										  boost::regex(".*", boost::regex::icase)));
    7.79  		HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
    7.80  													 0U,
    7.81  													 url_base,
    7.82 @@ -1702,18 +1715,54 @@
    7.83  		
    7.84  		// Issue a GET that *can* connect
    7.85  		mStatus = HttpStatus(200);
    7.86 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
    7.87 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
    7.88 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
    7.89 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
    7.90 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
    7.91 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
    7.92 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
    7.93 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
    7.94 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:.*", boost::regex::icase));
    7.95 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
    7.96 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-type:.*", boost::regex::icase));
    7.97 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
    7.98 +		handler.mHeadersRequired.push_back(
    7.99 +			regex_container_t::value_type(
   7.100 +				boost::regex("X-Reflect-connection", boost::regex::icase),
   7.101 +				boost::regex("keep-alive", boost::regex::icase)));
   7.102 +		handler.mHeadersRequired.push_back(
   7.103 +			regex_container_t::value_type(
   7.104 +				boost::regex("X-Reflect-accept", boost::regex::icase),
   7.105 +				boost::regex("\\*/\\*", boost::regex::icase)));
   7.106 +		handler.mHeadersRequired.push_back(
   7.107 +			regex_container_t::value_type(
   7.108 +				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
   7.109 +				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
   7.110 +		handler.mHeadersRequired.push_back(
   7.111 +			regex_container_t::value_type(
   7.112 +				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
   7.113 +				boost::regex("\\d+", boost::regex::icase)));
   7.114 +		handler.mHeadersRequired.push_back(
   7.115 +			regex_container_t::value_type(
   7.116 +				boost::regex("X-Reflect-host", boost::regex::icase),
   7.117 +				boost::regex(".*", boost::regex::icase)));
   7.118 +		handler.mHeadersDisallowed.push_back(
   7.119 +			regex_container_t::value_type(
   7.120 +				boost::regex("X-Reflect-cache-control", boost::regex::icase),
   7.121 +				boost::regex(".*", boost::regex::icase)));
   7.122 +		handler.mHeadersDisallowed.push_back(
   7.123 +			regex_container_t::value_type(
   7.124 +				boost::regex("X-Reflect-pragma", boost::regex::icase),
   7.125 +				boost::regex(".*", boost::regex::icase)));
   7.126 +		handler.mHeadersDisallowed.push_back(
   7.127 +			regex_container_t::value_type(
   7.128 +				boost::regex("X-Reflect-range", boost::regex::icase),
   7.129 +				boost::regex(".*", boost::regex::icase)));
   7.130 +		handler.mHeadersDisallowed.push_back(
   7.131 +			regex_container_t::value_type(
   7.132 +				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
   7.133 +				boost::regex(".*", boost::regex::icase)));
   7.134 +		handler.mHeadersDisallowed.push_back(
   7.135 +			regex_container_t::value_type(
   7.136 +				boost::regex("X-Reflect-referer", boost::regex::icase),
   7.137 +				boost::regex(".*", boost::regex::icase)));
   7.138 +		handler.mHeadersDisallowed.push_back(
   7.139 +			regex_container_t::value_type(
   7.140 +				boost::regex("X-Reflect-content-type", boost::regex::icase),
   7.141 +				boost::regex(".*", boost::regex::icase)));
   7.142 +		handler.mHeadersDisallowed.push_back(
   7.143 +			regex_container_t::value_type(
   7.144 +				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
   7.145 +				boost::regex(".*", boost::regex::icase)));
   7.146  		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
   7.147  											0U,
   7.148  											url_base + "reflect/",
   7.149 @@ -1735,23 +1784,60 @@
   7.150  
   7.151  		// Do a texture-style fetch
   7.152  		headers = new HttpHeaders;
   7.153 -		headers->mHeaders.push_back("Accept: image/x-j2c");
   7.154 +		headers->append("Accept", "image/x-j2c");
   7.155  		
   7.156  		mStatus = HttpStatus(200);
   7.157  		handler.mHeadersRequired.clear();
   7.158  		handler.mHeadersDisallowed.clear();
   7.159 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
   7.160 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*image/x-j2c", boost::regex::icase));
   7.161 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
   7.162 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
   7.163 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
   7.164 -		handler.mHeadersRequired.push_back(boost::regex("\\W*X-Reflect-range:.*", boost::regex::icase));
   7.165 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
   7.166 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
   7.167 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:.*", boost::regex::icase));
   7.168 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
   7.169 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-type:.*", boost::regex::icase));
   7.170 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
   7.171 +		handler.mHeadersRequired.push_back(
   7.172 +			regex_container_t::value_type(
   7.173 +				boost::regex("X-Reflect-connection", boost::regex::icase),
   7.174 +				boost::regex("keep-alive", boost::regex::icase)));
   7.175 +		handler.mHeadersRequired.push_back(
   7.176 +			regex_container_t::value_type(
   7.177 +				boost::regex("X-Reflect-accept", boost::regex::icase),
   7.178 +				boost::regex("image/x-j2c", boost::regex::icase)));
   7.179 +		handler.mHeadersRequired.push_back(
   7.180 +			regex_container_t::value_type(
   7.181 +				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
   7.182 +				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
   7.183 +		handler.mHeadersRequired.push_back(
   7.184 +			regex_container_t::value_type(
   7.185 +				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
   7.186 +				boost::regex("\\d+", boost::regex::icase)));
   7.187 +		handler.mHeadersRequired.push_back(
   7.188 +			regex_container_t::value_type(
   7.189 +				boost::regex("X-Reflect-host", boost::regex::icase),
   7.190 +				boost::regex(".*", boost::regex::icase)));
   7.191 +		handler.mHeadersRequired.push_back(
   7.192 +			regex_container_t::value_type(
   7.193 +				boost::regex("\\W*X-Reflect-range", boost::regex::icase),
   7.194 +				boost::regex(".*", boost::regex::icase)));
   7.195 +
   7.196 +		handler.mHeadersDisallowed.push_back(
   7.197 +			regex_container_t::value_type(
   7.198 +				boost::regex("X-Reflect-cache-control", boost::regex::icase),
   7.199 +				boost::regex(".*", boost::regex::icase)));
   7.200 +		handler.mHeadersDisallowed.push_back(
   7.201 +			regex_container_t::value_type(
   7.202 +				boost::regex("X-Reflect-pragma", boost::regex::icase),
   7.203 +				boost::regex(".*", boost::regex::icase)));
   7.204 +		handler.mHeadersDisallowed.push_back(
   7.205 +			regex_container_t::value_type(
   7.206 +				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
   7.207 +				boost::regex(".*", boost::regex::icase)));
   7.208 +		handler.mHeadersDisallowed.push_back(
   7.209 +			regex_container_t::value_type(
   7.210 +				boost::regex("X-Reflect-referer", boost::regex::icase),
   7.211 +				boost::regex(".*", boost::regex::icase)));
   7.212 +		handler.mHeadersDisallowed.push_back(
   7.213 +			regex_container_t::value_type(
   7.214 +				boost::regex("X-Reflect-content-type", boost::regex::icase),
   7.215 +				boost::regex(".*", boost::regex::icase)));
   7.216 +		handler.mHeadersDisallowed.push_back(
   7.217 +			regex_container_t::value_type(
   7.218 +				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
   7.219 +				boost::regex(".*", boost::regex::icase)));
   7.220  		handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
   7.221  										  0U,
   7.222  										  url_base + "reflect/",
   7.223 @@ -1892,20 +1978,63 @@
   7.224  			
   7.225  		// Issue a default POST
   7.226  		mStatus = HttpStatus(200);
   7.227 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
   7.228 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
   7.229 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
   7.230 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
   7.231 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
   7.232 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
   7.233 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-type:\\s*application/x-www-form-urlencoded", boost::regex::icase));
   7.234 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
   7.235 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
   7.236 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
   7.237 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
   7.238 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
   7.239 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
   7.240 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
   7.241 +		handler.mHeadersRequired.push_back(
   7.242 +			regex_container_t::value_type(
   7.243 +				boost::regex("X-Reflect-connection", boost::regex::icase),
   7.244 +				boost::regex("keep-alive", boost::regex::icase)));
   7.245 +		handler.mHeadersRequired.push_back(
   7.246 +			regex_container_t::value_type(
   7.247 +				boost::regex("X-Reflect-accept", boost::regex::icase),
   7.248 +				boost::regex("\\*/\\*", boost::regex::icase)));
   7.249 +		handler.mHeadersRequired.push_back(
   7.250 +			regex_container_t::value_type(
   7.251 +				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
   7.252 +				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
   7.253 +		handler.mHeadersRequired.push_back(
   7.254 +			regex_container_t::value_type(
   7.255 +				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
   7.256 +				boost::regex("\\d+", boost::regex::icase)));
   7.257 +		handler.mHeadersRequired.push_back(
   7.258 +			regex_container_t::value_type(
   7.259 +				boost::regex("X-Reflect-host", boost::regex::icase),
   7.260 +				boost::regex(".*", boost::regex::icase)));
   7.261 +		handler.mHeadersRequired.push_back(
   7.262 +			regex_container_t::value_type(
   7.263 +				boost::regex("X-Reflect-content-length", boost::regex::icase),
   7.264 +				boost::regex("\\d+", boost::regex::icase)));
   7.265 +		handler.mHeadersRequired.push_back(
   7.266 +			regex_container_t::value_type(
   7.267 +				boost::regex("X-Reflect-content-type", boost::regex::icase),
   7.268 +				boost::regex("application/x-www-form-urlencoded", boost::regex::icase)));
   7.269 +
   7.270 +		handler.mHeadersDisallowed.push_back(
   7.271 +			regex_container_t::value_type(
   7.272 +				boost::regex("X-Reflect-cache-control", boost::regex::icase),
   7.273 +				boost::regex(".*", boost::regex::icase)));
   7.274 +		handler.mHeadersDisallowed.push_back(
   7.275 +			regex_container_t::value_type(
   7.276 +				boost::regex("X-Reflect-pragma", boost::regex::icase),
   7.277 +				boost::regex(".*", boost::regex::icase)));
   7.278 +		handler.mHeadersDisallowed.push_back(
   7.279 +			regex_container_t::value_type(
   7.280 +				boost::regex("X-Reflect-range", boost::regex::icase),
   7.281 +				boost::regex(".*", boost::regex::icase)));
   7.282 +		handler.mHeadersDisallowed.push_back(
   7.283 +			regex_container_t::value_type(
   7.284 +				boost::regex("X-Reflect-referer", boost::regex::icase),
   7.285 +				boost::regex(".*", boost::regex::icase)));
   7.286 +		handler.mHeadersDisallowed.push_back(
   7.287 +			regex_container_t::value_type(
   7.288 +				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
   7.289 +				boost::regex(".*", boost::regex::icase)));
   7.290 +		handler.mHeadersDisallowed.push_back(
   7.291 +			regex_container_t::value_type(
   7.292 +				boost::regex("X-Reflect-expect", boost::regex::icase),
   7.293 +				boost::regex(".*", boost::regex::icase)));
   7.294 +		handler.mHeadersDisallowed.push_back(
   7.295 +			regex_container_t::value_type(
   7.296 +				boost::regex("X-Reflect-transfer_encoding", boost::regex::icase),
   7.297 +				boost::regex(".*chunked.*", boost::regex::icase)));
   7.298  		HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
   7.299  											 0U,
   7.300  											 url_base + "reflect/",
   7.301 @@ -2052,20 +2181,64 @@
   7.302  			
   7.303  		// Issue a default PUT
   7.304  		mStatus = HttpStatus(200);
   7.305 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
   7.306 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
   7.307 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
   7.308 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
   7.309 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
   7.310 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
   7.311 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
   7.312 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
   7.313 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
   7.314 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
   7.315 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
   7.316 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
   7.317 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
   7.318 -		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:.*", boost::regex::icase));
   7.319 +		handler.mHeadersRequired.push_back(
   7.320 +			regex_container_t::value_type(
   7.321 +				boost::regex("X-Reflect-connection", boost::regex::icase),
   7.322 +				boost::regex("keep-alive", boost::regex::icase)));
   7.323 +		handler.mHeadersRequired.push_back(
   7.324 +			regex_container_t::value_type(
   7.325 +				boost::regex("X-Reflect-accept", boost::regex::icase),
   7.326 +				boost::regex("\\*/\\*", boost::regex::icase)));
   7.327 +		handler.mHeadersRequired.push_back(
   7.328 +			regex_container_t::value_type(
   7.329 +				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
   7.330 +				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
   7.331 +		handler.mHeadersRequired.push_back(
   7.332 +			regex_container_t::value_type(
   7.333 +				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
   7.334 +				boost::regex("\\d+", boost::regex::icase)));
   7.335 +		handler.mHeadersRequired.push_back(
   7.336 +			regex_container_t::value_type(
   7.337 +				boost::regex("X-Reflect-host", boost::regex::icase),
   7.338 +				boost::regex(".*", boost::regex::icase)));
   7.339 +		handler.mHeadersRequired.push_back(
   7.340 +			regex_container_t::value_type(
   7.341 +				boost::regex("X-Reflect-content-length", boost::regex::icase),
   7.342 +				boost::regex("\\d+", boost::regex::icase)));
   7.343 +
   7.344 +		handler.mHeadersDisallowed.push_back(
   7.345 +			regex_container_t::value_type(
   7.346 +				boost::regex("X-Reflect-cache-control", boost::regex::icase),
   7.347 +				boost::regex(".*", boost::regex::icase)));
   7.348 +		handler.mHeadersDisallowed.push_back(
   7.349 +			regex_container_t::value_type(
   7.350 +				boost::regex("X-Reflect-pragma", boost::regex::icase),
   7.351 +				boost::regex(".*", boost::regex::icase)));
   7.352 +		handler.mHeadersDisallowed.push_back(
   7.353 +			regex_container_t::value_type(
   7.354 +				boost::regex("X-Reflect-range", boost::regex::icase),
   7.355 +				boost::regex(".*", boost::regex::icase)));
   7.356 +		handler.mHeadersDisallowed.push_back(
   7.357 +			regex_container_t::value_type(
   7.358 +				boost::regex("X-Reflect-referer", boost::regex::icase),
   7.359 +				boost::regex(".*", boost::regex::icase)));
   7.360 +		handler.mHeadersDisallowed.push_back(
   7.361 +			regex_container_t::value_type(
   7.362 +				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
   7.363 +				boost::regex(".*", boost::regex::icase)));
   7.364 +		handler.mHeadersDisallowed.push_back(
   7.365 +			regex_container_t::value_type(
   7.366 +				boost::regex("X-Reflect-expect", boost::regex::icase),
   7.367 +				boost::regex(".*", boost::regex::icase)));
   7.368 +		handler.mHeadersDisallowed.push_back(
   7.369 +			regex_container_t::value_type(
   7.370 +				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
   7.371 +				boost::regex(".*chunked.*", boost::regex::icase)));
   7.372 +		handler.mHeadersDisallowed.push_back(
   7.373 +			regex_container_t::value_type(
   7.374 +				boost::regex("X-Reflect-content-type", boost::regex::icase),
   7.375 +				boost::regex(".*", boost::regex::icase)));
   7.376 +
   7.377  		HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
   7.378  											0U,
   7.379  											url_base + "reflect/",
   7.380 @@ -2206,27 +2379,73 @@
   7.381  
   7.382  		// headers
   7.383  		headers = new HttpHeaders;
   7.384 -		headers->mHeaders.push_back("Keep-Alive: 120");
   7.385 -		headers->mHeaders.push_back("Accept-encoding: deflate");
   7.386 -		headers->mHeaders.push_back("Accept: text/plain");
   7.387 +		headers->append("Keep-Alive", "120");
   7.388 +		headers->append("Accept-encoding", "deflate");
   7.389 +		headers->append("Accept", "text/plain");
   7.390  
   7.391  		// Issue a GET with modified headers
   7.392  		mStatus = HttpStatus(200);
   7.393 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
   7.394 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*text/plain", boost::regex::icase));
   7.395 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*deflate", boost::regex::icase)); // close enough
   7.396 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*120", boost::regex::icase));
   7.397 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
   7.398 -		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
   7.399 -		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-keep-alive:\\s*300", boost::regex::icase));
   7.400 -		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
   7.401 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
   7.402 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
   7.403 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
   7.404 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:.*", boost::regex::icase));
   7.405 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
   7.406 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-type:.*", boost::regex::icase));
   7.407 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
   7.408 +		handler.mHeadersRequired.push_back(
   7.409 +			regex_container_t::value_type(
   7.410 +				boost::regex("X-Reflect-connection", boost::regex::icase),
   7.411 +				boost::regex("keep-alive", boost::regex::icase)));
   7.412 +		handler.mHeadersRequired.push_back(
   7.413 +			regex_container_t::value_type(
   7.414 +				boost::regex("X-Reflect-accept", boost::regex::icase),
   7.415 +				boost::regex("text/plain", boost::regex::icase)));
   7.416 +		handler.mHeadersRequired.push_back(
   7.417 +			regex_container_t::value_type(
   7.418 +				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
   7.419 +				boost::regex("deflate", boost::regex::icase))); // close enough
   7.420 +		handler.mHeadersRequired.push_back(
   7.421 +			regex_container_t::value_type(
   7.422 +				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
   7.423 +				boost::regex("120", boost::regex::icase)));
   7.424 +		handler.mHeadersRequired.push_back(
   7.425 +			regex_container_t::value_type(
   7.426 +				boost::regex("X-Reflect-host", boost::regex::icase),
   7.427 +				boost::regex(".*", boost::regex::icase)));
   7.428 +
   7.429 +		handler.mHeadersDisallowed.push_back(
   7.430 +			regex_container_t::value_type(
   7.431 +				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
   7.432 +				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
   7.433 +		handler.mHeadersDisallowed.push_back(
   7.434 +			regex_container_t::value_type(
   7.435 +				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
   7.436 +				boost::regex("300", boost::regex::icase)));
   7.437 +		handler.mHeadersDisallowed.push_back(
   7.438 +			regex_container_t::value_type(
   7.439 +				boost::regex("X-Reflect-accept", boost::regex::icase),
   7.440 +				boost::regex("\\*/\\*", boost::regex::icase)));
   7.441 +		handler.mHeadersDisallowed.push_back(
   7.442 +			regex_container_t::value_type(
   7.443 +				boost::regex("X-Reflect-cache-control", boost::regex::icase),
   7.444 +				boost::regex(".*", boost::regex::icase)));
   7.445 +		handler.mHeadersDisallowed.push_back(
   7.446 +			regex_container_t::value_type(
   7.447 +				boost::regex("X-Reflect-pragma", boost::regex::icase),
   7.448 +				boost::regex(".*", boost::regex::icase)));
   7.449 +		handler.mHeadersDisallowed.push_back(
   7.450 +			regex_container_t::value_type(
   7.451 +				boost::regex("X-Reflect-range", boost::regex::icase),
   7.452 +				boost::regex(".*", boost::regex::icase)));
   7.453 +		handler.mHeadersDisallowed.push_back(
   7.454 +			regex_container_t::value_type(
   7.455 +				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
   7.456 +				boost::regex(".*", boost::regex::icase)));
   7.457 +		handler.mHeadersDisallowed.push_back(
   7.458 +			regex_container_t::value_type(
   7.459 +				boost::regex("X-Reflect-referer", boost::regex::icase),
   7.460 +				boost::regex(".*", boost::regex::icase)));
   7.461 +		handler.mHeadersDisallowed.push_back(
   7.462 +			regex_container_t::value_type(
   7.463 +				boost::regex("X-Reflect-content-type", boost::regex::icase),
   7.464 +				boost::regex(".*", boost::regex::icase)));
   7.465 +		handler.mHeadersDisallowed.push_back(
   7.466 +			regex_container_t::value_type(
   7.467 +				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
   7.468 +				boost::regex(".*", boost::regex::icase)));
   7.469  		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
   7.470  											0U,
   7.471  											url_base + "reflect/",
   7.472 @@ -2359,10 +2578,10 @@
   7.473  
   7.474  		// headers
   7.475  		headers = new HttpHeaders();
   7.476 -		headers->mHeaders.push_back("keep-Alive: 120");
   7.477 -		headers->mHeaders.push_back("Accept:  text/html");
   7.478 -		headers->mHeaders.push_back("content-type:  application/llsd+xml");
   7.479 -		headers->mHeaders.push_back("cache-control: no-store");
   7.480 +		headers->append("keep-Alive", "120");
   7.481 +		headers->append("Accept", "text/html");
   7.482 +		headers->append("content-type", "application/llsd+xml");
   7.483 +		headers->append("cache-control", "no-store");
   7.484  		
   7.485  		// And a buffer array
   7.486  		const char * msg("<xml><llsd><string>It was the best of times, it was the worst of times.</string></llsd></xml>");
   7.487 @@ -2371,23 +2590,76 @@
   7.488  			
   7.489  		// Issue a default POST
   7.490  		mStatus = HttpStatus(200);
   7.491 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
   7.492 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*text/html", boost::regex::icase));
   7.493 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
   7.494 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*120", boost::regex::icase));
   7.495 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
   7.496 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
   7.497 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-type:\\s*application/llsd\\+xml", boost::regex::icase));
   7.498 -		handler.mHeadersRequired.push_back(boost::regex("\\s*X-Reflect-cache-control:\\s*no-store", boost::regex::icase));
   7.499 -		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:\\s*application/x-www-form-urlencoded", boost::regex::icase));
   7.500 -		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
   7.501 -		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-keep-alive:\\s*300", boost::regex::icase));
   7.502 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
   7.503 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
   7.504 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
   7.505 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
   7.506 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
   7.507 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
   7.508 +		handler.mHeadersRequired.push_back(
   7.509 +			regex_container_t::value_type(
   7.510 +				boost::regex("X-Reflect-connection", boost::regex::icase),
   7.511 +				boost::regex("keep-alive", boost::regex::icase)));
   7.512 +		handler.mHeadersRequired.push_back(
   7.513 +			regex_container_t::value_type(
   7.514 +				boost::regex("X-Reflect-accept", boost::regex::icase),
   7.515 +				boost::regex("text/html", boost::regex::icase)));
   7.516 +		handler.mHeadersRequired.push_back(
   7.517 +			regex_container_t::value_type(
   7.518 +				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
   7.519 +				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
   7.520 +		handler.mHeadersRequired.push_back(
   7.521 +			regex_container_t::value_type(
   7.522 +				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
   7.523 +				boost::regex("120", boost::regex::icase)));
   7.524 +		handler.mHeadersRequired.push_back(
   7.525 +			regex_container_t::value_type(
   7.526 +				boost::regex("X-Reflect-host", boost::regex::icase),
   7.527 +				boost::regex(".*", boost::regex::icase)));
   7.528 +		handler.mHeadersRequired.push_back(
   7.529 +			regex_container_t::value_type(
   7.530 +				boost::regex("X-Reflect-content-length", boost::regex::icase),
   7.531 +				boost::regex("\\d+", boost::regex::icase)));
   7.532 +		handler.mHeadersRequired.push_back(
   7.533 +			regex_container_t::value_type(
   7.534 +				boost::regex("X-Reflect-content-type", boost::regex::icase),
   7.535 +				boost::regex("application/llsd\\+xml", boost::regex::icase)));
   7.536 +		handler.mHeadersRequired.push_back(
   7.537 +			regex_container_t::value_type(
   7.538 +				boost::regex("X-Reflect-cache-control", boost::regex::icase),
   7.539 +				boost::regex("no-store", boost::regex::icase)));
   7.540 +
   7.541 +		handler.mHeadersDisallowed.push_back(
   7.542 +			regex_container_t::value_type(
   7.543 +				boost::regex("X-Reflect-content-type", boost::regex::icase),
   7.544 +				boost::regex("application/x-www-form-urlencoded", boost::regex::icase)));
   7.545 +		handler.mHeadersDisallowed.push_back(
   7.546 +			regex_container_t::value_type(
   7.547 +				boost::regex("X-Reflect-accept", boost::regex::icase),
   7.548 +				boost::regex("\\*/\\*", boost::regex::icase)));
   7.549 +		handler.mHeadersDisallowed.push_back(
   7.550 +			regex_container_t::value_type(
   7.551 +				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
   7.552 +				boost::regex("300", boost::regex::icase)));
   7.553 +		handler.mHeadersDisallowed.push_back(
   7.554 +			regex_container_t::value_type(
   7.555 +				boost::regex("X-Reflect-pragma", boost::regex::icase),
   7.556 +				boost::regex(".*", boost::regex::icase)));
   7.557 +		handler.mHeadersDisallowed.push_back(
   7.558 +			regex_container_t::value_type(
   7.559 +				boost::regex("X-Reflect-range", boost::regex::icase),
   7.560 +				boost::regex(".*", boost::regex::icase)));
   7.561 +		handler.mHeadersDisallowed.push_back(
   7.562 +			regex_container_t::value_type(
   7.563 +				boost::regex("X-Reflect-referer", boost::regex::icase),
   7.564 +				boost::regex(".*", boost::regex::icase)));
   7.565 +		handler.mHeadersDisallowed.push_back(
   7.566 +			regex_container_t::value_type(
   7.567 +				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
   7.568 +				boost::regex(".*", boost::regex::icase)));
   7.569 +		handler.mHeadersDisallowed.push_back(
   7.570 +			regex_container_t::value_type(
   7.571 +				boost::regex("X-Reflect-expect", boost::regex::icase),
   7.572 +				boost::regex(".*", boost::regex::icase)));
   7.573 +		handler.mHeadersDisallowed.push_back(
   7.574 +			regex_container_t::value_type(
   7.575 +				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
   7.576 +				boost::regex(".*", boost::regex::icase)));
   7.577 +
   7.578  		HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
   7.579  											 0U,
   7.580  											 url_base + "reflect/",
   7.581 @@ -2529,9 +2801,9 @@
   7.582  
   7.583  		// headers
   7.584  		headers = new HttpHeaders;
   7.585 -		headers->mHeaders.push_back("content-type:  text/plain");
   7.586 -		headers->mHeaders.push_back("content-type:  text/html");
   7.587 -		headers->mHeaders.push_back("content-type:  application/llsd+xml");
   7.588 +		headers->append("content-type", "text/plain");
   7.589 +		headers->append("content-type", "text/html");
   7.590 +		headers->append("content-type", "application/llsd+xml");
   7.591  		
   7.592  		// And a buffer array
   7.593  		const char * msg("<xml><llsd><string>It was the best of times, it was the worst of times.</string></llsd></xml>");
   7.594 @@ -2540,22 +2812,71 @@
   7.595  			
   7.596  		// Issue a default PUT
   7.597  		mStatus = HttpStatus(200);
   7.598 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
   7.599 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
   7.600 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
   7.601 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
   7.602 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
   7.603 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
   7.604 -		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-type:\\s*application/llsd\\+xml", boost::regex::icase));
   7.605 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
   7.606 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
   7.607 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
   7.608 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
   7.609 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
   7.610 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
   7.611 -		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
   7.612 -		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:\\s*text/plain", boost::regex::icase));
   7.613 -		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:\\s*text/html", boost::regex::icase));
   7.614 +		handler.mHeadersRequired.push_back(
   7.615 +			regex_container_t::value_type(
   7.616 +				boost::regex("X-Reflect-connection", boost::regex::icase),
   7.617 +				boost::regex("keep-alive", boost::regex::icase)));
   7.618 +		handler.mHeadersRequired.push_back(
   7.619 +			regex_container_t::value_type(
   7.620 +				boost::regex("X-Reflect-accept", boost::regex::icase),
   7.621 +				boost::regex("\\*/\\*", boost::regex::icase)));
   7.622 +		handler.mHeadersRequired.push_back(
   7.623 +			regex_container_t::value_type(
   7.624 +				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
   7.625 +				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
   7.626 +		handler.mHeadersRequired.push_back(
   7.627 +			regex_container_t::value_type(
   7.628 +				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
   7.629 +				boost::regex("\\d+", boost::regex::icase)));
   7.630 +		handler.mHeadersRequired.push_back(
   7.631 +			regex_container_t::value_type(
   7.632 +				boost::regex("X-Reflect-host", boost::regex::icase),
   7.633 +				boost::regex(".*", boost::regex::icase)));
   7.634 +		handler.mHeadersRequired.push_back(
   7.635 +			regex_container_t::value_type(
   7.636 +				boost::regex("X-Reflect-content-length", boost::regex::icase),
   7.637 +				boost::regex("\\d+", boost::regex::icase)));
   7.638 +		handler.mHeadersRequired.push_back(
   7.639 +			regex_container_t::value_type(
   7.640 +				boost::regex("X-Reflect-content-type", boost::regex::icase),
   7.641 +				boost::regex("application/llsd\\+xml", boost::regex::icase)));
   7.642 +
   7.643 +		handler.mHeadersDisallowed.push_back(
   7.644 +			regex_container_t::value_type(
   7.645 +				boost::regex("X-Reflect-cache-control", boost::regex::icase),
   7.646 +				boost::regex(".*", boost::regex::icase)));
   7.647 +		handler.mHeadersDisallowed.push_back(
   7.648 +			regex_container_t::value_type(
   7.649 +				boost::regex("X-Reflect-pragma", boost::regex::icase),
   7.650 +				boost::regex(".*", boost::regex::icase)));
   7.651 +		handler.mHeadersDisallowed.push_back(
   7.652 +			regex_container_t::value_type(
   7.653 +				boost::regex("X-Reflect-range", boost::regex::icase),
   7.654 +				boost::regex(".*", boost::regex::icase)));
   7.655 +		handler.mHeadersDisallowed.push_back(
   7.656 +			regex_container_t::value_type(
   7.657 +				boost::regex("X-Reflect-referer", boost::regex::icase),
   7.658 +				boost::regex(".*", boost::regex::icase)));
   7.659 +		handler.mHeadersDisallowed.push_back(
   7.660 +			regex_container_t::value_type(
   7.661 +				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
   7.662 +				boost::regex(".*", boost::regex::icase)));
   7.663 +		handler.mHeadersDisallowed.push_back(
   7.664 +			regex_container_t::value_type(
   7.665 +				boost::regex("X-Reflect-expect", boost::regex::icase),
   7.666 +				boost::regex(".*", boost::regex::icase)));
   7.667 +		handler.mHeadersDisallowed.push_back(
   7.668 +			regex_container_t::value_type(
   7.669 +				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
   7.670 +				boost::regex(".*", boost::regex::icase)));
   7.671 +		handler.mHeadersDisallowed.push_back(
   7.672 +			regex_container_t::value_type(
   7.673 +				boost::regex("X-Reflect-content-type", boost::regex::icase),
   7.674 +				boost::regex("text/plain", boost::regex::icase)));
   7.675 +		handler.mHeadersDisallowed.push_back(
   7.676 +			regex_container_t::value_type(
   7.677 +				boost::regex("X-Reflect-content-type", boost::regex::icase),
   7.678 +				boost::regex("text/html", boost::regex::icase)));
   7.679  		HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
   7.680  											0U,
   7.681  											url_base + "reflect/",
     8.1 --- a/indra/newview/lltexturefetch.cpp	Wed Jun 19 13:55:54 2013 -0400
     8.2 +++ b/indra/newview/lltexturefetch.cpp	Mon Apr 15 16:55:35 2013 +0000
     8.3 @@ -2376,6 +2376,7 @@
     8.4  	  mQAMode(qa_mode),
     8.5  	  mHttpRequest(NULL),
     8.6  	  mHttpOptions(NULL),
     8.7 +	  mHttpOptionsWithHeaders(NULL),
     8.8  	  mHttpHeaders(NULL),
     8.9  	  mHttpMetricsHeaders(NULL),
    8.10  	  mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
    8.11 @@ -2406,10 +2407,12 @@
    8.12  	
    8.13  	mHttpRequest = new LLCore::HttpRequest;
    8.14  	mHttpOptions = new LLCore::HttpOptions;
    8.15 +	mHttpOptionsWithHeaders = new LLCore::HttpOptions;
    8.16 +	mHttpOptionsWithHeaders->setWantHeaders(true);
    8.17  	mHttpHeaders = new LLCore::HttpHeaders;
    8.18 -	mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c");
    8.19 +	mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C);
    8.20  	mHttpMetricsHeaders = new LLCore::HttpHeaders;
    8.21 -	mHttpMetricsHeaders->mHeaders.push_back("Content-Type: application/llsd+xml");
    8.22 +	mHttpMetricsHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
    8.23  	mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_TEXTURE);
    8.24  }
    8.25  
    8.26 @@ -2430,6 +2433,12 @@
    8.27  		mHttpOptions = NULL;
    8.28  	}
    8.29  
    8.30 +	if (mHttpOptionsWithHeaders)
    8.31 +	{
    8.32 +		mHttpOptionsWithHeaders->release();
    8.33 +		mHttpOptionsWithHeaders = NULL;
    8.34 +	}
    8.35 +
    8.36  	if (mHttpHeaders)
    8.37  	{
    8.38  		mHttpHeaders->release();
    8.39 @@ -4041,7 +4050,7 @@
    8.40  	if (! mHttpHeaders)
    8.41  	{
    8.42  		mHttpHeaders = new LLCore::HttpHeaders;
    8.43 -		mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c");
    8.44 +		mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C);
    8.45  	}
    8.46  }
    8.47  
     9.1 --- a/indra/newview/lltexturefetch.h	Wed Jun 19 13:55:54 2013 -0400
     9.2 +++ b/indra/newview/lltexturefetch.h	Mon Apr 15 16:55:35 2013 +0000
     9.3 @@ -4,7 +4,7 @@
     9.4   *
     9.5   * $LicenseInfo:firstyear=2000&license=viewerlgpl$
     9.6   * Second Life Viewer Source Code
     9.7 - * Copyright (C) 2012, Linden Research, Inc.
     9.8 + * Copyright (C) 2012-2013, Linden Research, Inc.
     9.9   * 
    9.10   * This library is free software; you can redistribute it and/or
    9.11   * modify it under the terms of the GNU Lesser General Public
    9.12 @@ -351,6 +351,7 @@
    9.13  	// LLCurl interfaces used in the past.
    9.14  	LLCore::HttpRequest *				mHttpRequest;					// Ttf
    9.15  	LLCore::HttpOptions *				mHttpOptions;					// Ttf
    9.16 +	LLCore::HttpOptions *				mHttpOptionsWithHeaders;		// Ttf
    9.17  	LLCore::HttpHeaders *				mHttpHeaders;					// Ttf
    9.18  	LLCore::HttpHeaders *				mHttpMetricsHeaders;			// Ttf
    9.19  	LLCore::HttpRequest::policy_t		mHttpPolicyClass;				// T*

mercurial