diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-10-13 13:24:50 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-10-14 10:57:25 +0000 |
commit | af3d4809763ef308f08ced947a73b624729ac7ea (patch) | |
tree | 4402b911e30383f6c6dace1e8cf3b8e85355db3a /chromium/net/http | |
parent | 0e8ff63a407fe323e215bb1a2c423c09a4747c8a (diff) | |
download | qtwebengine-chromium-af3d4809763ef308f08ced947a73b624729ac7ea.tar.gz |
BASELINE: Update Chromium to 47.0.2526.14
Also adding in sources needed for spellchecking.
Change-Id: Idd44170fa1616f26315188970a8d5ba7d472b18a
Reviewed-by: Michael BrĂ¼ning <michael.bruning@theqtcompany.com>
Diffstat (limited to 'chromium/net/http')
75 files changed, 8508 insertions, 4313 deletions
diff --git a/chromium/net/http/des.cc b/chromium/net/http/des.cc index 17aae4da684..874372f3873 100644 --- a/chromium/net/http/des.cc +++ b/chromium/net/http/des.cc @@ -9,22 +9,15 @@ #if defined(USE_OPENSSL) #include <openssl/des.h> #include "crypto/openssl_util.h" -#elif defined(USE_NSS_CERTS) -#include <nss.h> -#include <pk11pub.h> -#include "crypto/nss_util.h" -#elif defined(OS_MACOSX) +#elif defined(OS_IOS) #include <CommonCrypto/CommonCryptor.h> -#elif defined(OS_WIN) -#include <windows.h> -#include <wincrypt.h> -#include "crypto/scoped_capi_types.h" +#else +#error "Unknown platform" #endif -// The Mac and Windows (CryptoAPI) versions of DESEncrypt are our own code. -// DESSetKeyParity, DESMakeKey, and the Linux (NSS) version of DESEncrypt are -// based on mozilla/security/manager/ssl/src/nsNTLMAuthModule.cpp, -// CVS rev. 1.14. +// The iOS version of DESEncrypt is our own code. +// DESSetKeyParity and DESMakeKey are based on +// mozilla/security/manager/ssl/src/nsNTLMAuthModule.cpp, CVS rev. 1.14. /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 @@ -100,64 +93,7 @@ void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { reinterpret_cast<DES_cblock*>(hash), &ks, DES_ENCRYPT); } -#elif defined(USE_NSS_CERTS) - -void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { - CK_MECHANISM_TYPE cipher_mech = CKM_DES_ECB; - PK11SlotInfo* slot = NULL; - PK11SymKey* symkey = NULL; - PK11Context* ctxt = NULL; - SECItem key_item; - SECItem* param = NULL; - SECStatus rv; - unsigned int n; - - crypto::EnsureNSSInit(); - - slot = PK11_GetInternalSlot(); - if (!slot) - goto done; - - key_item.data = const_cast<uint8*>(key); - key_item.len = 8; - symkey = PK11_ImportSymKey(slot, cipher_mech, - PK11_OriginUnwrap, CKA_ENCRYPT, - &key_item, NULL); - if (!symkey) - goto done; - - // No initialization vector required. - param = PK11_ParamFromIV(cipher_mech, NULL); - if (!param) - goto done; - - ctxt = PK11_CreateContextBySymKey(cipher_mech, CKA_ENCRYPT, - symkey, param); - if (!ctxt) - goto done; - - rv = PK11_CipherOp(ctxt, hash, reinterpret_cast<int*>(&n), 8, - const_cast<uint8*>(src), 8); - if (rv != SECSuccess) - goto done; - - // TODO(wtc): Should this be PK11_Finalize? - rv = PK11_DigestFinal(ctxt, hash+8, &n, 0); - if (rv != SECSuccess) - goto done; - - done: - if (ctxt) - PK11_DestroyContext(ctxt, PR_TRUE); - if (symkey) - PK11_FreeSymKey(symkey); - if (param) - SECITEM_FreeItem(param, PR_TRUE); - if (slot) - PK11_FreeSlot(slot); -} - -#elif defined(OS_MACOSX) +#elif defined(OS_IOS) void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { CCCryptorStatus status; @@ -168,53 +104,6 @@ void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { DCHECK(data_out_moved == 8); } -#elif defined(OS_WIN) - -void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { - crypto::ScopedHCRYPTPROV provider; - if (!CryptAcquireContext(provider.receive(), NULL, NULL, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT)) - return; - - { - // Import the DES key. - struct KeyBlob { - BLOBHEADER header; - DWORD key_size; - BYTE key_data[8]; - }; - KeyBlob key_blob; - key_blob.header.bType = PLAINTEXTKEYBLOB; - key_blob.header.bVersion = CUR_BLOB_VERSION; - key_blob.header.reserved = 0; - key_blob.header.aiKeyAlg = CALG_DES; - key_blob.key_size = 8; // 64 bits - memcpy(key_blob.key_data, key, 8); - - crypto::ScopedHCRYPTKEY key; - BOOL import_ok = CryptImportKey(provider, - reinterpret_cast<BYTE*>(&key_blob), - sizeof key_blob, 0, 0, key.receive()); - // Destroy the copy of the key. - SecureZeroMemory(key_blob.key_data, sizeof key_blob.key_data); - if (!import_ok) - return; - - // No initialization vector required. - DWORD cipher_mode = CRYPT_MODE_ECB; - if (!CryptSetKeyParam(key, KP_MODE, reinterpret_cast<BYTE*>(&cipher_mode), - 0)) - return; - - // CryptoAPI requires us to copy the plaintext to the output buffer first. - CopyMemory(hash, src, 8); - // Pass a 'Final' of FALSE, otherwise CryptEncrypt appends one additional - // block of padding to the data. - DWORD hash_len = 8; - CryptEncrypt(key, 0, FALSE, 0, hash, &hash_len, 8); - } -} - #endif } // namespace net diff --git a/chromium/net/http/failing_http_transaction_factory.cc b/chromium/net/http/failing_http_transaction_factory.cc index 89e5329d5d9..adb96914ad0 100644 --- a/chromium/net/http/failing_http_transaction_factory.cc +++ b/chromium/net/http/failing_http_transaction_factory.cc @@ -4,6 +4,8 @@ #include "net/http/failing_http_transaction_factory.h" +#include <stdint.h> + #include "base/bind.h" #include "base/compiler_specific.h" #include "base/location.h" @@ -48,13 +50,15 @@ class FailingHttpTransaction : public HttpTransaction { const CompletionCallback& callback) override; void StopCaching() override; bool GetFullRequestHeaders(HttpRequestHeaders* headers) const override; - int64 GetTotalReceivedBytes() const override; + int64_t GetTotalReceivedBytes() const override; + int64_t GetTotalSentBytes() const override; void DoneReading() override; const HttpResponseInfo* GetResponseInfo() const override; LoadState GetLoadState() const override; UploadProgress GetUploadProgress() const override; void SetQuicServerInfo(QuicServerInfo* quic_server_info) override; bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; + bool GetRemoteEndpoint(IPEndPoint* endpoint) const override; void SetPriority(RequestPriority priority) override; void SetWebSocketHandshakeStreamCreateHelper( WebSocketHandshakeStreamBase::CreateHelper* create_helper) override; @@ -122,6 +126,10 @@ int64 FailingHttpTransaction::GetTotalReceivedBytes() const { return 0; } +int64_t FailingHttpTransaction::GetTotalSentBytes() const { + return 0; +} + void FailingHttpTransaction::DoneReading() { NOTREACHED(); } @@ -147,6 +155,10 @@ bool FailingHttpTransaction::GetLoadTimingInfo( return false; } +bool FailingHttpTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const { + return false; +} + void FailingHttpTransaction::SetPriority(RequestPriority priority) {} void FailingHttpTransaction::SetWebSocketHandshakeStreamCreateHelper( diff --git a/chromium/net/http/http_auth_handler_factory.cc b/chromium/net/http/http_auth_handler_factory.cc index 4f09c9f23c9..5a89964a80c 100644 --- a/chromium/net/http/http_auth_handler_factory.cc +++ b/chromium/net/http/http_auth_handler_factory.cc @@ -43,11 +43,11 @@ int HttpAuthHandlerFactory::CreatePreemptiveAuthHandlerFromString( } // static -HttpAuthHandlerRegistryFactory* HttpAuthHandlerFactory::CreateDefault( - HostResolver* host_resolver) { +scoped_ptr<HttpAuthHandlerRegistryFactory> +HttpAuthHandlerFactory::CreateDefault(HostResolver* host_resolver) { DCHECK(host_resolver); - HttpAuthHandlerRegistryFactory* registry_factory = - new HttpAuthHandlerRegistryFactory(); + scoped_ptr<HttpAuthHandlerRegistryFactory> registry_factory = + make_scoped_ptr(new HttpAuthHandlerRegistryFactory()); registry_factory->RegisterSchemeFactory( "basic", new HttpAuthHandlerBasic::Factory()); registry_factory->RegisterSchemeFactory( @@ -106,7 +106,7 @@ void HttpAuthHandlerRegistryFactory::SetURLSecurityManager( void HttpAuthHandlerRegistryFactory::RegisterSchemeFactory( const std::string& scheme, HttpAuthHandlerFactory* factory) { - std::string lower_scheme = base::StringToLowerASCII(scheme); + std::string lower_scheme = base::ToLowerASCII(scheme); FactoryMap::iterator it = factory_map_.find(lower_scheme); if (it != factory_map_.end()) { delete it->second; @@ -119,7 +119,7 @@ void HttpAuthHandlerRegistryFactory::RegisterSchemeFactory( HttpAuthHandlerFactory* HttpAuthHandlerRegistryFactory::GetSchemeFactory( const std::string& scheme) const { - std::string lower_scheme = base::StringToLowerASCII(scheme); + std::string lower_scheme = base::ToLowerASCII(scheme); FactoryMap::const_iterator it = factory_map_.find(lower_scheme); if (it == factory_map_.end()) { return NULL; // |scheme| is not registered. @@ -190,7 +190,7 @@ int HttpAuthHandlerRegistryFactory::CreateAuthHandler( handler->reset(); return ERR_INVALID_RESPONSE; } - std::string lower_scheme = base::StringToLowerASCII(scheme); + std::string lower_scheme = base::ToLowerASCII(scheme); FactoryMap::iterator it = factory_map_.find(lower_scheme); if (it == factory_map_.end()) { handler->reset(); diff --git a/chromium/net/http/http_auth_handler_factory.h b/chromium/net/http/http_auth_handler_factory.h index 30b1896ce96..1261bedd567 100644 --- a/chromium/net/http/http_auth_handler_factory.h +++ b/chromium/net/http/http_auth_handler_factory.h @@ -115,7 +115,8 @@ class NET_EXPORT HttpAuthHandlerFactory { // non-NULL. |resolver| must remain valid for the lifetime of the // HttpAuthHandlerRegistryFactory and any HttpAuthHandlers created by said // factory. - static HttpAuthHandlerRegistryFactory* CreateDefault(HostResolver* resolver); + static scoped_ptr<HttpAuthHandlerRegistryFactory> CreateDefault( + HostResolver* resolver); private: // The URL security manager diff --git a/chromium/net/http/http_auth_handler_ntlm_portable.cc b/chromium/net/http/http_auth_handler_ntlm_portable.cc index 5e1d5faedc5..54d4492a4bf 100644 --- a/chromium/net/http/http_auth_handler_ntlm_portable.cc +++ b/chromium/net/http/http_auth_handler_ntlm_portable.cc @@ -261,7 +261,7 @@ static void LM_Hash(const base::string16& password, uint8* hash) { // Convert password to OEM character set. We'll just use the native // filesystem charset. std::string passbuf = base::SysWideToNativeMB(base::UTF16ToWide(password)); - base::StringToUpperASCII(&passbuf); + passbuf = base::ToUpperASCII(passbuf); passbuf.resize(14, '\0'); uint8 k1[8], k2[8]; diff --git a/chromium/net/http/http_auth_multi_round_parse.cc b/chromium/net/http/http_auth_multi_round_parse.cc index efee2bbcf65..1d0edac08b8 100644 --- a/chromium/net/http/http_auth_multi_round_parse.cc +++ b/chromium/net/http/http_auth_multi_round_parse.cc @@ -17,7 +17,7 @@ bool SchemeIsValid(const std::string& scheme, // There is no guarantee that challenge->scheme() is valid ASCII, but // LowerCaseEqualsASCII will do the right thing even if it isn't. return base::LowerCaseEqualsASCII(challenge->scheme(), - base::StringToLowerASCII(scheme).c_str()); + base::ToLowerASCII(scheme)); } } // namespace diff --git a/chromium/net/http/http_basic_stream.cc b/chromium/net/http/http_basic_stream.cc index 0d14e0f9a0e..436127f31b8 100644 --- a/chromium/net/http/http_basic_stream.cc +++ b/chromium/net/http/http_basic_stream.cc @@ -67,26 +67,28 @@ bool HttpBasicStream::IsResponseBodyComplete() const { return parser()->IsResponseBodyComplete(); } -bool HttpBasicStream::CanFindEndOfResponse() const { - return parser()->CanFindEndOfResponse(); -} - bool HttpBasicStream::IsConnectionReused() const { return parser()->IsConnectionReused(); } void HttpBasicStream::SetConnectionReused() { parser()->SetConnectionReused(); } -bool HttpBasicStream::IsConnectionReusable() const { - return parser()->IsConnectionReusable(); +bool HttpBasicStream::CanReuseConnection() const { + return parser()->CanReuseConnection(); } -int64 HttpBasicStream::GetTotalReceivedBytes() const { +int64_t HttpBasicStream::GetTotalReceivedBytes() const { if (parser()) return parser()->received_bytes(); return 0; } +int64_t HttpBasicStream::GetTotalSentBytes() const { + if (parser()) + return parser()->sent_bytes(); + return 0; +} + bool HttpBasicStream::GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const { return state_.connection()->GetLoadTimingInfo(IsConnectionReused(), @@ -102,7 +104,12 @@ void HttpBasicStream::GetSSLCertRequestInfo( parser()->GetSSLCertRequestInfo(cert_request_info); } -bool HttpBasicStream::IsSpdyHttpStream() const { return false; } +bool HttpBasicStream::GetRemoteEndpoint(IPEndPoint* endpoint) { + if (!state_.connection() || !state_.connection()->socket()) + return false; + + return state_.connection()->socket()->GetPeerAddress(endpoint) == OK; +} void HttpBasicStream::Drain(HttpNetworkSession* session) { HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this); diff --git a/chromium/net/http/http_basic_stream.h b/chromium/net/http/http_basic_stream.h index 194f7ef6c20..c9428d6fb1f 100644 --- a/chromium/net/http/http_basic_stream.h +++ b/chromium/net/http/http_basic_stream.h @@ -9,6 +9,8 @@ #ifndef NET_HTTP_HTTP_BASIC_STREAM_H_ #define NET_HTTP_HTTP_BASIC_STREAM_H_ +#include <stdint.h> + #include <string> #include "base/basictypes.h" @@ -56,15 +58,15 @@ class HttpBasicStream : public HttpStream { bool IsResponseBodyComplete() const override; - bool CanFindEndOfResponse() const override; - bool IsConnectionReused() const override; void SetConnectionReused() override; - bool IsConnectionReusable() const override; + bool CanReuseConnection() const override; + + int64_t GetTotalReceivedBytes() const override; - int64 GetTotalReceivedBytes() const override; + int64_t GetTotalSentBytes() const override; bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; @@ -72,7 +74,7 @@ class HttpBasicStream : public HttpStream { void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override; - bool IsSpdyHttpStream() const override; + bool GetRemoteEndpoint(IPEndPoint* endpoint) override; void Drain(HttpNetworkSession* session) override; diff --git a/chromium/net/http/http_cache.h b/chromium/net/http/http_cache.h index 8300c29048c..026d476e92f 100644 --- a/chromium/net/http/http_cache.h +++ b/chromium/net/http/http_cache.h @@ -170,6 +170,7 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory, // referenced by |url|, as long as the entry's |expected_response_time| has // not changed. This method returns without blocking, and the operation will // be performed asynchronously without any completion notification. + // Takes ownership of |buf|. void WriteMetadata(const GURL& url, RequestPriority priority, base::Time expected_response_time, diff --git a/chromium/net/http/http_cache_transaction.cc b/chromium/net/http/http_cache_transaction.cc index f2fcf4cb7c4..9dd8458e2e2 100644 --- a/chromium/net/http/http_cache_transaction.cc +++ b/chromium/net/http/http_cache_transaction.cc @@ -14,6 +14,7 @@ #include <string> #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/format_macros.h" #include "base/location.h" @@ -236,8 +237,8 @@ static bool HeaderMatches(const HttpRequestHeaders& headers, HttpUtil::ValuesIterator v(header_value.begin(), header_value.end(), ','); while (v.GetNext()) { - if (base::LowerCaseEqualsASCII(v.value_begin(), v.value_end(), - search->value)) + if (base::LowerCaseEqualsASCII( + base::StringPiece(v.value_begin(), v.value_end()), search->value)) return true; } } @@ -255,7 +256,6 @@ HttpCache::Transaction::Transaction(RequestPriority priority, HttpCache* cache) new_entry_(NULL), new_response_(NULL), mode_(NONE), - target_state_(STATE_NONE), reading_(false), invalid_range_(false), truncated_(false), @@ -274,6 +274,7 @@ HttpCache::Transaction::Transaction(RequestPriority priority, HttpCache* cache) write_len_(0), transaction_pattern_(PATTERN_UNDEFINED), total_received_bytes_(0), + total_sent_bytes_(0), websocket_handshake_stream_base_create_helper_(NULL), weak_factory_(this) { static_assert(HttpCache::Transaction::kNumValidationHeaders == @@ -327,7 +328,7 @@ bool HttpCache::Transaction::AddTruncatedFlag() { DCHECK(mode_ & WRITE || mode_ == NONE); // Don't set the flag for sparse entries. - if (partial_.get() && !truncated_) + if (partial_ && !truncated_) return true; if (!CanResume(true)) @@ -338,7 +339,6 @@ bool HttpCache::Transaction::AddTruncatedFlag() { return true; truncated_ = true; - target_state_ = STATE_NONE; next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE; DoLoop(OK); return true; @@ -367,6 +367,7 @@ int HttpCache::Transaction::Start(const HttpRequestInfo* request, DCHECK(!reading_); DCHECK(!network_trans_.get()); DCHECK(!entry_); + DCHECK_EQ(next_state_, STATE_NONE); if (!cache_.get()) return ERR_UNEXPECTED; @@ -453,6 +454,7 @@ bool HttpCache::Transaction::IsReadyToRestartForAuth() { int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { + DCHECK_EQ(next_state_, STATE_NONE); DCHECK(buf); DCHECK_GT(buf_len, 0); DCHECK(!callback.is_null()); @@ -473,29 +475,19 @@ int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, } reading_ = true; - int rv; - - switch (mode_) { - case READ_WRITE: - DCHECK(partial_.get()); - if (!network_trans_.get()) { - // We are just reading from the cache, but we may be writing later. - rv = ReadFromEntry(buf, buf_len); - break; - } - case NONE: - case WRITE: - DCHECK(network_trans_.get()); - rv = ReadFromNetwork(buf, buf_len); - break; - case READ: - rv = ReadFromEntry(buf, buf_len); - break; - default: - NOTREACHED(); - rv = ERR_FAILED; + read_buf_ = buf; + io_buf_len_ = buf_len; + if (network_trans_) { + DCHECK(mode_ == WRITE || mode_ == NONE || + (mode_ == READ_WRITE && partial_)); + next_state_ = STATE_NETWORK_READ; + } else { + DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_)); + next_state_ = STATE_CACHE_READ_DATA; } + int rv = DoLoop(OK); + if (rv == ERR_IO_PENDING) { DCHECK(callback_.is_null()); callback_ = callback; @@ -530,13 +522,20 @@ bool HttpCache::Transaction::GetFullRequestHeaders( return false; } -int64 HttpCache::Transaction::GetTotalReceivedBytes() const { - int64 total_received_bytes = total_received_bytes_; +int64_t HttpCache::Transaction::GetTotalReceivedBytes() const { + int64_t total_received_bytes = total_received_bytes_; if (network_trans_) total_received_bytes += network_trans_->GetTotalReceivedBytes(); return total_received_bytes; } +int64_t HttpCache::Transaction::GetTotalSentBytes() const { + int64_t total_sent_bytes = total_sent_bytes_; + if (network_trans_) + total_sent_bytes += network_trans_->GetTotalSentBytes(); + return total_sent_bytes; +} + void HttpCache::Transaction::DoneReading() { if (cache_.get() && entry_) { DCHECK_NE(mode_, UPDATE); @@ -600,6 +599,18 @@ bool HttpCache::Transaction::GetLoadTimingInfo( return true; } +bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const { + if (network_trans_) + return network_trans_->GetRemoteEndpoint(endpoint); + + if (!old_remote_endpoint_.address().empty()) { + *endpoint = old_remote_endpoint_; + return true; + } + + return false; +} + void HttpCache::Transaction::SetPriority(RequestPriority priority) { priority_ = priority; if (network_trans_) @@ -644,26 +655,6 @@ void HttpCache::Transaction::GetConnectionAttempts( //----------------------------------------------------------------------------- -void HttpCache::Transaction::DoCallback(int rv) { - DCHECK(rv != ERR_IO_PENDING); - DCHECK(!callback_.is_null()); - - read_buf_ = NULL; // Release the buffer before invoking the callback. - - // Since Run may result in Read being called, clear callback_ up front. - CompletionCallback c = callback_; - callback_.Reset(); - c.Run(rv); -} - -int HttpCache::Transaction::HandleResult(int rv) { - DCHECK(rv != ERR_IO_PENDING); - if (!callback_.is_null()) - DoCallback(rv); - - return rv; -} - // A few common patterns: (Foo* means Foo -> FooComplete) // // 1. Not-cached entry: @@ -690,8 +681,9 @@ int HttpCache::Transaction::HandleResult(int rv) { // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* // -> CacheDispatchValidation -> BeginPartialCacheValidation() -> // BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest -> -// UpdateCachedResponse -> CacheWriteResponse* -> UpdateCachedResponseComplete -// -> OverwriteCachedResponse -> PartialHeadersReceived +// UpdateCachedResponse -> CacheWriteUpdatedResponse* -> +// UpdateCachedResponseComplete -> OverwriteCachedResponse -> +// PartialHeadersReceived // // Read(): // CacheReadData* @@ -714,8 +706,9 @@ int HttpCache::Transaction::HandleResult(int rv) { // CacheQueryData* -> ValidateEntryHeadersAndContinue() -> // StartPartialCacheValidation -> CompletePartialCacheValidation -> // BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest -> -// UpdateCachedResponse -> CacheWriteResponse* -> UpdateCachedResponseComplete -// -> OverwriteCachedResponse -> PartialHeadersReceived +// UpdateCachedResponse -> CacheWriteUpdatedResponse* -> +// UpdateCachedResponseComplete -> OverwriteCachedResponse -> +// PartialHeadersReceived // // Read() 1: // NetworkRead* -> CacheWriteData* @@ -804,24 +797,6 @@ int HttpCache::Transaction::DoLoop(int result) { case STATE_GET_BACKEND_COMPLETE: rv = DoGetBackendComplete(rv); break; - case STATE_SEND_REQUEST: - DCHECK_EQ(OK, rv); - rv = DoSendRequest(); - break; - case STATE_SEND_REQUEST_COMPLETE: - rv = DoSendRequestComplete(rv); - break; - case STATE_SUCCESSFUL_SEND_REQUEST: - DCHECK_EQ(OK, rv); - rv = DoSuccessfulSendRequest(); - break; - case STATE_NETWORK_READ: - DCHECK_EQ(OK, rv); - rv = DoNetworkRead(); - break; - case STATE_NETWORK_READ_COMPLETE: - rv = DoNetworkReadComplete(rv); - break; case STATE_INIT_ENTRY: DCHECK_EQ(OK, rv); rv = DoInitEntry(); @@ -833,13 +808,6 @@ int HttpCache::Transaction::DoLoop(int result) { case STATE_OPEN_ENTRY_COMPLETE: rv = DoOpenEntryComplete(rv); break; - case STATE_CREATE_ENTRY: - DCHECK_EQ(OK, rv); - rv = DoCreateEntry(); - break; - case STATE_CREATE_ENTRY_COMPLETE: - rv = DoCreateEntryComplete(rv); - break; case STATE_DOOM_ENTRY: DCHECK_EQ(OK, rv); rv = DoDoomEntry(); @@ -847,6 +815,13 @@ int HttpCache::Transaction::DoLoop(int result) { case STATE_DOOM_ENTRY_COMPLETE: rv = DoDoomEntryComplete(rv); break; + case STATE_CREATE_ENTRY: + DCHECK_EQ(OK, rv); + rv = DoCreateEntry(); + break; + case STATE_CREATE_ENTRY_COMPLETE: + rv = DoCreateEntryComplete(rv); + break; case STATE_ADD_TO_ENTRY: DCHECK_EQ(OK, rv); rv = DoAddToEntry(); @@ -854,6 +829,31 @@ int HttpCache::Transaction::DoLoop(int result) { case STATE_ADD_TO_ENTRY_COMPLETE: rv = DoAddToEntryComplete(rv); break; + case STATE_CACHE_READ_RESPONSE: + DCHECK_EQ(OK, rv); + rv = DoCacheReadResponse(); + break; + case STATE_CACHE_READ_RESPONSE_COMPLETE: + rv = DoCacheReadResponseComplete(rv); + break; + case STATE_TOGGLE_UNUSED_SINCE_PREFETCH: + DCHECK_EQ(OK, rv); + rv = DoCacheToggleUnusedSincePrefetch(); + break; + case STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE: + rv = DoCacheToggleUnusedSincePrefetchComplete(rv); + break; + case STATE_CACHE_DISPATCH_VALIDATION: + DCHECK_EQ(OK, rv); + rv = DoCacheDispatchValidation(); + break; + case STATE_CACHE_QUERY_DATA: + DCHECK_EQ(OK, rv); + rv = DoCacheQueryData(); + break; + case STATE_CACHE_QUERY_DATA_COMPLETE: + rv = DoCacheQueryDataComplete(rv); + break; case STATE_START_PARTIAL_CACHE_VALIDATION: DCHECK_EQ(OK, rv); rv = DoStartPartialCacheValidation(); @@ -861,10 +861,28 @@ int HttpCache::Transaction::DoLoop(int result) { case STATE_COMPLETE_PARTIAL_CACHE_VALIDATION: rv = DoCompletePartialCacheValidation(rv); break; + case STATE_SEND_REQUEST: + DCHECK_EQ(OK, rv); + rv = DoSendRequest(); + break; + case STATE_SEND_REQUEST_COMPLETE: + rv = DoSendRequestComplete(rv); + break; + case STATE_SUCCESSFUL_SEND_REQUEST: + DCHECK_EQ(OK, rv); + rv = DoSuccessfulSendRequest(); + break; case STATE_UPDATE_CACHED_RESPONSE: DCHECK_EQ(OK, rv); rv = DoUpdateCachedResponse(); break; + case STATE_CACHE_WRITE_UPDATED_RESPONSE: + DCHECK_EQ(OK, rv); + rv = DoCacheWriteUpdatedResponse(); + break; + case STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE: + rv = DoCacheWriteUpdatedResponseComplete(rv); + break; case STATE_UPDATE_CACHED_RESPONSE_COMPLETE: rv = DoUpdateCachedResponseComplete(rv); break; @@ -872,6 +890,13 @@ int HttpCache::Transaction::DoLoop(int result) { DCHECK_EQ(OK, rv); rv = DoOverwriteCachedResponse(); break; + case STATE_CACHE_WRITE_RESPONSE: + DCHECK_EQ(OK, rv); + rv = DoCacheWriteResponse(); + break; + case STATE_CACHE_WRITE_RESPONSE_COMPLETE: + rv = DoCacheWriteResponseComplete(rv); + break; case STATE_TRUNCATE_CACHED_DATA: DCHECK_EQ(OK, rv); rv = DoTruncateCachedData(); @@ -890,35 +915,6 @@ int HttpCache::Transaction::DoLoop(int result) { DCHECK_EQ(OK, rv); rv = DoPartialHeadersReceived(); break; - case STATE_CACHE_READ_RESPONSE: - DCHECK_EQ(OK, rv); - rv = DoCacheReadResponse(); - break; - case STATE_CACHE_READ_RESPONSE_COMPLETE: - rv = DoCacheReadResponseComplete(rv); - break; - case STATE_CACHE_DISPATCH_VALIDATION: - DCHECK_EQ(OK, rv); - rv = DoCacheDispatchValidation(); - break; - case STATE_TOGGLE_UNUSED_SINCE_PREFETCH: - DCHECK_EQ(OK, rv); - rv = DoCacheToggleUnusedSincePrefetch(); - break; - case STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE: - rv = DoCacheToggleUnusedSincePrefetchComplete(rv); - break; - case STATE_CACHE_WRITE_RESPONSE: - DCHECK_EQ(OK, rv); - rv = DoCacheWriteResponse(); - break; - case STATE_CACHE_WRITE_TRUNCATED_RESPONSE: - DCHECK_EQ(OK, rv); - rv = DoCacheWriteTruncatedResponse(); - break; - case STATE_CACHE_WRITE_RESPONSE_COMPLETE: - rv = DoCacheWriteResponseComplete(rv); - break; case STATE_CACHE_READ_METADATA: DCHECK_EQ(OK, rv); rv = DoCacheReadMetadata(); @@ -926,12 +922,12 @@ int HttpCache::Transaction::DoLoop(int result) { case STATE_CACHE_READ_METADATA_COMPLETE: rv = DoCacheReadMetadataComplete(rv); break; - case STATE_CACHE_QUERY_DATA: + case STATE_NETWORK_READ: DCHECK_EQ(OK, rv); - rv = DoCacheQueryData(); + rv = DoNetworkRead(); break; - case STATE_CACHE_QUERY_DATA_COMPLETE: - rv = DoCacheQueryDataComplete(rv); + case STATE_NETWORK_READ_COMPLETE: + rv = DoNetworkReadComplete(rv); break; case STATE_CACHE_READ_DATA: DCHECK_EQ(OK, rv); @@ -946,6 +942,13 @@ int HttpCache::Transaction::DoLoop(int result) { case STATE_CACHE_WRITE_DATA_COMPLETE: rv = DoCacheWriteDataComplete(rv); break; + case STATE_CACHE_WRITE_TRUNCATED_RESPONSE: + DCHECK_EQ(OK, rv); + rv = DoCacheWriteTruncatedResponse(); + break; + case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE: + rv = DoCacheWriteTruncatedResponseComplete(rv); + break; default: NOTREACHED() << "bad state"; rv = ERR_FAILED; @@ -953,8 +956,10 @@ int HttpCache::Transaction::DoLoop(int result) { } } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); - if (rv != ERR_IO_PENDING) - HandleResult(rv); + if (rv != ERR_IO_PENDING && !callback_.is_null()) { + read_buf_ = NULL; // Release the buffer before invoking the callback. + base::ResetAndReturn(&callback_).Run(rv); + } return rv; } @@ -1016,7 +1021,7 @@ int HttpCache::Transaction::DoGetBackendComplete(int result) { return ERR_CACHE_MISS; if (mode_ == NONE) { - if (partial_.get()) { + if (partial_) { partial_->RestoreHeaders(&custom_request_->extra_headers); partial_.reset(); } @@ -1031,192 +1036,6 @@ int HttpCache::Transaction::DoGetBackendComplete(int result) { return OK; } -int HttpCache::Transaction::DoSendRequest() { - DCHECK(mode_ & WRITE || mode_ == NONE); - DCHECK(!network_trans_.get()); - - send_request_since_ = TimeTicks::Now(); - - // Create a network transaction. - int rv = cache_->network_layer_->CreateTransaction(priority_, - &network_trans_); - if (rv != OK) - return rv; - network_trans_->SetBeforeNetworkStartCallback(before_network_start_callback_); - network_trans_->SetBeforeProxyHeadersSentCallback( - before_proxy_headers_sent_callback_); - - // Old load timing information, if any, is now obsolete. - old_network_trans_load_timing_.reset(); - - if (websocket_handshake_stream_base_create_helper_) - network_trans_->SetWebSocketHandshakeStreamCreateHelper( - websocket_handshake_stream_base_create_helper_); - - next_state_ = STATE_SEND_REQUEST_COMPLETE; - rv = network_trans_->Start(request_, io_callback_, net_log_); - return rv; -} - -int HttpCache::Transaction::DoSendRequestComplete(int result) { - if (!cache_.get()) - return ERR_UNEXPECTED; - - // If we tried to conditionalize the request and failed, we know - // we won't be reading from the cache after this point. - if (couldnt_conditionalize_request_) - mode_ = WRITE; - - if (result == OK) { - next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; - return OK; - } - - const HttpResponseInfo* response = network_trans_->GetResponseInfo(); - response_.network_accessed = response->network_accessed; - - // Do not record requests that have network errors or restarts. - UpdateTransactionPattern(PATTERN_NOT_COVERED); - if (IsCertificateError(result)) { - // If we get a certificate error, then there is a certificate in ssl_info, - // so GetResponseInfo() should never return NULL here. - DCHECK(response); - response_.ssl_info = response->ssl_info; - } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { - DCHECK(response); - response_.cert_request_info = response->cert_request_info; - } else if (response_.was_cached) { - DoneWritingToEntry(true); - } - - return result; -} - -// We received the response headers and there is no error. -int HttpCache::Transaction::DoSuccessfulSendRequest() { - DCHECK(!new_response_); - const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); - - if (new_response->headers->response_code() == 401 || - new_response->headers->response_code() == 407) { - auth_response_ = *new_response; - if (!reading_) - return OK; - - // We initiated a second request the caller doesn't know about. We should be - // able to authenticate this request because we should have authenticated - // this URL moments ago. - if (IsReadyToRestartForAuth()) { - DCHECK(!response_.auth_challenge.get()); - next_state_ = STATE_SEND_REQUEST_COMPLETE; - // In theory we should check to see if there are new cookies, but there - // is no way to do that from here. - return network_trans_->RestartWithAuth(AuthCredentials(), io_callback_); - } - - // We have to perform cleanup at this point so that at least the next - // request can succeed. We do not retry at this point, because data - // has been read and we have no way to gather credentials. We would - // fail again, and potentially loop. This can happen if the credentials - // expire while chrome is suspended. - if (entry_) - DoomPartialEntry(false); - mode_ = NONE; - partial_.reset(); - ResetNetworkTransaction(); - return ERR_CACHE_AUTH_FAILURE_AFTER_READ; - } - - new_response_ = new_response; - if (!ValidatePartialResponse() && !auth_response_.headers.get()) { - // Something went wrong with this request and we have to restart it. - // If we have an authentication response, we are exposed to weird things - // hapenning if the user cancels the authentication before we receive - // the new response. - net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST); - UpdateTransactionPattern(PATTERN_NOT_COVERED); - response_ = HttpResponseInfo(); - ResetNetworkTransaction(); - new_response_ = NULL; - next_state_ = STATE_SEND_REQUEST; - return OK; - } - - if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) { - // We have stored the full entry, but it changed and the server is - // sending a range. We have to delete the old entry. - UpdateTransactionPattern(PATTERN_NOT_COVERED); - DoneWritingToEntry(false); - } - - if (mode_ == WRITE && - transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) { - UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED); - } - - // Invalidate any cached GET with a successful PUT or DELETE. - if (mode_ == WRITE && - (request_->method == "PUT" || request_->method == "DELETE")) { - if (NonErrorResponse(new_response->headers->response_code())) { - int ret = cache_->DoomEntry(cache_key_, NULL); - DCHECK_EQ(OK, ret); - } - cache_->DoneWritingToEntry(entry_, true); - entry_ = NULL; - mode_ = NONE; - } - - // Invalidate any cached GET with a successful POST. - if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) && - request_->method == "POST" && - NonErrorResponse(new_response->headers->response_code())) { - cache_->DoomMainEntryForUrl(request_->url); - } - - RecordNoStoreHeaderHistogram(request_->load_flags, new_response); - - if (new_response_->headers->response_code() == 416 && - (request_->method == "GET" || request_->method == "POST")) { - // If there is an active entry it may be destroyed with this transaction. - response_ = *new_response_; - return OK; - } - - // Are we expecting a response to a conditional query? - if (mode_ == READ_WRITE || mode_ == UPDATE) { - if (new_response->headers->response_code() == 304 || handling_206_) { - UpdateTransactionPattern(PATTERN_ENTRY_VALIDATED); - next_state_ = STATE_UPDATE_CACHED_RESPONSE; - return OK; - } - UpdateTransactionPattern(PATTERN_ENTRY_UPDATED); - mode_ = WRITE; - } - - next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; - return OK; -} - -int HttpCache::Transaction::DoNetworkRead() { - next_state_ = STATE_NETWORK_READ_COMPLETE; - return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_); -} - -int HttpCache::Transaction::DoNetworkReadComplete(int result) { - DCHECK(mode_ & WRITE || mode_ == NONE); - - if (!cache_.get()) - return ERR_UNEXPECTED; - - // If there is an error or we aren't saving the data, we are done; just wait - // until the destructor runs to see if we can keep the data. - if (mode_ == NONE || result < 0) - return result; - - next_state_ = STATE_CACHE_WRITE_DATA; - return result; -} - int HttpCache::Transaction::DoInitEntry() { DCHECK(!new_entry_); @@ -1282,6 +1101,24 @@ int HttpCache::Transaction::DoOpenEntryComplete(int result) { return ERR_CACHE_MISS; } +int HttpCache::Transaction::DoDoomEntry() { + next_state_ = STATE_DOOM_ENTRY_COMPLETE; + cache_pending_ = true; + if (first_cache_access_since_.is_null()) + first_cache_access_since_ = TimeTicks::Now(); + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY); + return cache_->DoomEntry(cache_key_, this); +} + +int HttpCache::Transaction::DoDoomEntryComplete(int result) { + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result); + next_state_ = STATE_CREATE_ENTRY; + cache_pending_ = false; + if (result == ERR_CACHE_RACE) + next_state_ = STATE_INIT_ENTRY; + return OK; +} + int HttpCache::Transaction::DoCreateEntry() { DCHECK(!new_entry_); next_state_ = STATE_CREATE_ENTRY_COMPLETE; @@ -1297,45 +1134,29 @@ int HttpCache::Transaction::DoCreateEntryComplete(int result) { net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY, result); cache_pending_ = false; - next_state_ = STATE_ADD_TO_ENTRY; + switch (result) { + case OK: + next_state_ = STATE_ADD_TO_ENTRY; + break; - if (result == ERR_CACHE_RACE) { - next_state_ = STATE_INIT_ENTRY; - return OK; - } + case ERR_CACHE_RACE: + next_state_ = STATE_INIT_ENTRY; + break; - if (result != OK) { - // We have a race here: Maybe we failed to open the entry and decided to - // create one, but by the time we called create, another transaction already - // created the entry. If we want to eliminate this issue, we need an atomic - // OpenOrCreate() method exposed by the disk cache. - DLOG(WARNING) << "Unable to create cache entry"; - mode_ = NONE; - if (partial_.get()) - partial_->RestoreHeaders(&custom_request_->extra_headers); - next_state_ = STATE_SEND_REQUEST; + default: + // We have a race here: Maybe we failed to open the entry and decided to + // create one, but by the time we called create, another transaction + // already created the entry. If we want to eliminate this issue, we + // need an atomic OpenOrCreate() method exposed by the disk cache. + DLOG(WARNING) << "Unable to create cache entry"; + mode_ = NONE; + if (partial_) + partial_->RestoreHeaders(&custom_request_->extra_headers); + next_state_ = STATE_SEND_REQUEST; } return OK; } -int HttpCache::Transaction::DoDoomEntry() { - next_state_ = STATE_DOOM_ENTRY_COMPLETE; - cache_pending_ = true; - if (first_cache_access_since_.is_null()) - first_cache_access_since_ = TimeTicks::Now(); - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY); - return cache_->DoomEntry(cache_key_, this); -} - -int HttpCache::Transaction::DoDoomEntryComplete(int result) { - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result); - next_state_ = STATE_CREATE_ENTRY; - cache_pending_ = false; - if (result == ERR_CACHE_RACE) - next_state_ = STATE_INIT_ENTRY; - return OK; -} - int HttpCache::Transaction::DoAddToEntry() { DCHECK(new_entry_); cache_pending_ = true; @@ -1416,7 +1237,7 @@ int HttpCache::Transaction::DoAddToEntryComplete(int result) { } if (mode_ == WRITE) { - if (partial_.get()) + if (partial_) partial_->RestoreHeaders(&custom_request_->extra_headers); next_state_ = STATE_SEND_REQUEST; } else { @@ -1427,6 +1248,121 @@ int HttpCache::Transaction::DoAddToEntryComplete(int result) { return OK; } +int HttpCache::Transaction::DoCacheReadResponse() { + DCHECK(entry_); + next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE; + + io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex); + read_buf_ = new IOBuffer(io_buf_len_); + + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO); + return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(), + io_buf_len_, io_callback_); +} + +int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); + if (result != io_buf_len_ || + !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, &response_, + &truncated_)) { + return OnCacheReadError(result, true); + } + + // cert_cache() will be null if the CertCacheTrial field trial is disabled. + if (cache_->cert_cache() && response_.ssl_info.is_valid()) + ReadCertChain(); + + // Some resources may have slipped in as truncated when they're not. + int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); + if (response_.headers->GetContentLength() == current_size) + truncated_ = false; + + if ((response_.unused_since_prefetch && + !(request_->load_flags & LOAD_PREFETCH)) || + (!response_.unused_since_prefetch && + (request_->load_flags & LOAD_PREFETCH))) { + // Either this is the first use of an entry since it was prefetched or + // this is a prefetch. The value of response.unused_since_prefetch is valid + // for this transaction but the bit needs to be flipped in storage. + next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH; + return OK; + } + + next_state_ = STATE_CACHE_DISPATCH_VALIDATION; + return OK; +} + +int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch() { + // Write back the toggled value for the next use of this entry. + response_.unused_since_prefetch = !response_.unused_since_prefetch; + + // TODO(jkarlin): If DoUpdateCachedResponse is also called for this + // transaction then metadata will be written to cache twice. If prefetching + // becomes more common, consider combining the writes. + + // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch")); + + next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE; + return WriteResponseInfoToEntry(false); +} + +int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete( + int result) { + // Restore the original value for this transaction. + response_.unused_since_prefetch = !response_.unused_since_prefetch; + next_state_ = STATE_CACHE_DISPATCH_VALIDATION; + return OnWriteResponseInfoToEntryComplete(result); +} + +int HttpCache::Transaction::DoCacheDispatchValidation() { + // We now have access to the cache entry. + // + // o if we are a reader for the transaction, then we can start reading the + // cache entry. + // + // o if we can read or write, then we should check if the cache entry needs + // to be validated and then issue a network request if needed or just read + // from the cache if the cache entry is already valid. + // + // o if we are set to UPDATE, then we are handling an externally + // conditionalized request (if-modified-since / if-none-match). We check + // if the request headers define a validation request. + // + int result = ERR_FAILED; + switch (mode_) { + case READ: + UpdateTransactionPattern(PATTERN_ENTRY_USED); + result = BeginCacheRead(); + break; + case READ_WRITE: + result = BeginPartialCacheValidation(); + break; + case UPDATE: + result = BeginExternallyConditionalizedRequest(); + break; + case WRITE: + default: + NOTREACHED(); + } + return result; +} + +int HttpCache::Transaction::DoCacheQueryData() { + next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE; + return entry_->disk_entry->ReadyForSparseIO(io_callback_); +} + +int HttpCache::Transaction::DoCacheQueryDataComplete(int result) { + DCHECK_EQ(OK, result); + if (!cache_.get()) + return ERR_UNEXPECTED; + + return ValidateEntryHeadersAndContinue(); +} + // We may end up here multiple times for a given request. int HttpCache::Transaction::DoStartPartialCacheValidation() { if (mode_ == NONE) @@ -1462,6 +1398,173 @@ int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) { return BeginCacheValidation(); } +int HttpCache::Transaction::DoSendRequest() { + DCHECK(mode_ & WRITE || mode_ == NONE); + DCHECK(!network_trans_.get()); + + send_request_since_ = TimeTicks::Now(); + + // Create a network transaction. + int rv = + cache_->network_layer_->CreateTransaction(priority_, &network_trans_); + if (rv != OK) + return rv; + network_trans_->SetBeforeNetworkStartCallback(before_network_start_callback_); + network_trans_->SetBeforeProxyHeadersSentCallback( + before_proxy_headers_sent_callback_); + + // Old load timing information, if any, is now obsolete. + old_network_trans_load_timing_.reset(); + old_remote_endpoint_ = IPEndPoint(); + + if (websocket_handshake_stream_base_create_helper_) + network_trans_->SetWebSocketHandshakeStreamCreateHelper( + websocket_handshake_stream_base_create_helper_); + + next_state_ = STATE_SEND_REQUEST_COMPLETE; + rv = network_trans_->Start(request_, io_callback_, net_log_); + return rv; +} + +int HttpCache::Transaction::DoSendRequestComplete(int result) { + if (!cache_.get()) + return ERR_UNEXPECTED; + + // If we tried to conditionalize the request and failed, we know + // we won't be reading from the cache after this point. + if (couldnt_conditionalize_request_) + mode_ = WRITE; + + if (result == OK) { + next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; + return OK; + } + + const HttpResponseInfo* response = network_trans_->GetResponseInfo(); + response_.network_accessed = response->network_accessed; + + // Do not record requests that have network errors or restarts. + UpdateTransactionPattern(PATTERN_NOT_COVERED); + if (IsCertificateError(result)) { + // If we get a certificate error, then there is a certificate in ssl_info, + // so GetResponseInfo() should never return NULL here. + DCHECK(response); + response_.ssl_info = response->ssl_info; + } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { + DCHECK(response); + response_.cert_request_info = response->cert_request_info; + } else if (response_.was_cached) { + DoneWritingToEntry(true); + } + + return result; +} + +// We received the response headers and there is no error. +int HttpCache::Transaction::DoSuccessfulSendRequest() { + DCHECK(!new_response_); + const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); + + if (new_response->headers->response_code() == 401 || + new_response->headers->response_code() == 407) { + auth_response_ = *new_response; + if (!reading_) + return OK; + + // We initiated a second request the caller doesn't know about. We should be + // able to authenticate this request because we should have authenticated + // this URL moments ago. + if (IsReadyToRestartForAuth()) { + DCHECK(!response_.auth_challenge.get()); + next_state_ = STATE_SEND_REQUEST_COMPLETE; + // In theory we should check to see if there are new cookies, but there + // is no way to do that from here. + return network_trans_->RestartWithAuth(AuthCredentials(), io_callback_); + } + + // We have to perform cleanup at this point so that at least the next + // request can succeed. We do not retry at this point, because data + // has been read and we have no way to gather credentials. We would + // fail again, and potentially loop. This can happen if the credentials + // expire while chrome is suspended. + if (entry_) + DoomPartialEntry(false); + mode_ = NONE; + partial_.reset(); + ResetNetworkTransaction(); + return ERR_CACHE_AUTH_FAILURE_AFTER_READ; + } + + new_response_ = new_response; + if (!ValidatePartialResponse() && !auth_response_.headers.get()) { + // Something went wrong with this request and we have to restart it. + // If we have an authentication response, we are exposed to weird things + // hapenning if the user cancels the authentication before we receive + // the new response. + net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST); + UpdateTransactionPattern(PATTERN_NOT_COVERED); + response_ = HttpResponseInfo(); + ResetNetworkTransaction(); + new_response_ = NULL; + next_state_ = STATE_SEND_REQUEST; + return OK; + } + + if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) { + // We have stored the full entry, but it changed and the server is + // sending a range. We have to delete the old entry. + UpdateTransactionPattern(PATTERN_NOT_COVERED); + DoneWritingToEntry(false); + } + + if (mode_ == WRITE && + transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) { + UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED); + } + + // Invalidate any cached GET with a successful PUT or DELETE. + if (mode_ == WRITE && + (request_->method == "PUT" || request_->method == "DELETE")) { + if (NonErrorResponse(new_response->headers->response_code())) { + int ret = cache_->DoomEntry(cache_key_, NULL); + DCHECK_EQ(OK, ret); + } + cache_->DoneWritingToEntry(entry_, true); + entry_ = NULL; + mode_ = NONE; + } + + // Invalidate any cached GET with a successful POST. + if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) && + request_->method == "POST" && + NonErrorResponse(new_response->headers->response_code())) { + cache_->DoomMainEntryForUrl(request_->url); + } + + RecordNoStoreHeaderHistogram(request_->load_flags, new_response); + + if (new_response_->headers->response_code() == 416 && + (request_->method == "GET" || request_->method == "POST")) { + // If there is an active entry it may be destroyed with this transaction. + response_ = *new_response_; + return OK; + } + + // Are we expecting a response to a conditional query? + if (mode_ == READ_WRITE || mode_ == UPDATE) { + if (new_response->headers->response_code() == 304 || handling_206_) { + UpdateTransactionPattern(PATTERN_ENTRY_VALIDATED); + next_state_ = STATE_UPDATE_CACHED_RESPONSE; + return OK; + } + UpdateTransactionPattern(PATTERN_ENTRY_UPDATED); + mode_ = WRITE; + } + + next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; + return OK; +} + // We received 304 or 206 and we want to update the cached response headers. int HttpCache::Transaction::DoUpdateCachedResponse() { next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; @@ -1493,14 +1596,28 @@ int HttpCache::Transaction::DoUpdateCachedResponse() { // If we are already reading, we already updated the headers for this // request; doing it again will change Content-Length. if (!reading_) { - target_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; - next_state_ = STATE_CACHE_WRITE_RESPONSE; + next_state_ = STATE_CACHE_WRITE_UPDATED_RESPONSE; rv = OK; } } return rv; } +int HttpCache::Transaction::DoCacheWriteUpdatedResponse() { + // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 HttpCache::Transaction::DoCacheWriteUpdatedResponse")); + + next_state_ = STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE; + return WriteResponseInfoToEntry(false); +} + +int HttpCache::Transaction::DoCacheWriteUpdatedResponseComplete(int result) { + next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; + return OnWriteResponseInfoToEntryComplete(result); +} + int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) { if (mode_ == UPDATE) { DCHECK(!handling_206_); @@ -1512,7 +1629,7 @@ int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) { DoneWritingToEntry(true); } else if (entry_ && !handling_206_) { DCHECK_EQ(READ_WRITE, mode_); - if (!partial_.get() || partial_->IsLastRange()) { + if (!partial_ || partial_->IsLastRange()) { cache_->ConvertWriterToReader(entry_); mode_ = READ; } @@ -1541,7 +1658,7 @@ int HttpCache::Transaction::DoOverwriteCachedResponse() { } // We change the value of Content-Length for partial content. - if (handling_206_ && partial_.get()) + if (handling_206_ && partial_) partial_->FixContentLength(new_response_->headers.get()); response_ = *new_response_; @@ -1558,18 +1675,31 @@ int HttpCache::Transaction::DoOverwriteCachedResponse() { // There is no point in storing this resource because it will never be used. // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries. DoneWritingToEntry(false); - if (partial_.get()) + if (partial_) partial_->FixResponseHeaders(response_.headers.get(), true); next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; return OK; } - target_state_ = STATE_TRUNCATE_CACHED_DATA; - next_state_ = truncated_ ? STATE_CACHE_WRITE_TRUNCATED_RESPONSE : - STATE_CACHE_WRITE_RESPONSE; + next_state_ = STATE_CACHE_WRITE_RESPONSE; return OK; } +int HttpCache::Transaction::DoCacheWriteResponse() { + // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "422516 HttpCache::Transaction::DoCacheWriteResponse")); + + next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; + return WriteResponseInfoToEntry(truncated_); +} + +int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { + next_state_ = STATE_TRUNCATE_CACHED_DATA; + return OnWriteResponseInfoToEntryComplete(result); +} + int HttpCache::Transaction::DoTruncateCachedData() { next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE; if (!entry_) @@ -1616,11 +1746,10 @@ int HttpCache::Transaction::DoTruncateCachedMetadataComplete(int result) { int HttpCache::Transaction::DoPartialHeadersReceived() { new_response_ = NULL; - if (entry_ && !partial_.get() && - entry_->disk_entry->GetDataSize(kMetadataIndex)) + if (entry_ && !partial_ && entry_->disk_entry->GetDataSize(kMetadataIndex)) next_state_ = STATE_CACHE_READ_METADATA; - if (!partial_.get()) + if (!partial_) return OK; if (reading_) { @@ -1637,142 +1766,6 @@ int HttpCache::Transaction::DoPartialHeadersReceived() { return OK; } -int HttpCache::Transaction::DoCacheReadResponse() { - DCHECK(entry_); - next_state_ = STATE_CACHE_READ_RESPONSE_COMPLETE; - - io_buf_len_ = entry_->disk_entry->GetDataSize(kResponseInfoIndex); - read_buf_ = new IOBuffer(io_buf_len_); - - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO); - return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_.get(), - io_buf_len_, io_callback_); -} - -int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); - if (result != io_buf_len_ || - !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, - &response_, &truncated_)) { - return OnCacheReadError(result, true); - } - - // cert_cache() will be null if the CertCacheTrial field trial is disabled. - if (cache_->cert_cache() && response_.ssl_info.is_valid()) - ReadCertChain(); - - // Some resources may have slipped in as truncated when they're not. - int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); - if (response_.headers->GetContentLength() == current_size) - truncated_ = false; - - if ((response_.unused_since_prefetch && - !(request_->load_flags & LOAD_PREFETCH)) || - (!response_.unused_since_prefetch && - (request_->load_flags & LOAD_PREFETCH))) { - // Either this is the first use of an entry since it was prefetched or - // this is a prefetch. The value of response.unused_since_prefetch is valid - // for this transaction but the bit needs to be flipped in storage. - next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH; - return OK; - } - - next_state_ = STATE_CACHE_DISPATCH_VALIDATION; - return OK; -} - -int HttpCache::Transaction::DoCacheDispatchValidation() { - // We now have access to the cache entry. - // - // o if we are a reader for the transaction, then we can start reading the - // cache entry. - // - // o if we can read or write, then we should check if the cache entry needs - // to be validated and then issue a network request if needed or just read - // from the cache if the cache entry is already valid. - // - // o if we are set to UPDATE, then we are handling an externally - // conditionalized request (if-modified-since / if-none-match). We check - // if the request headers define a validation request. - // - int result = ERR_FAILED; - switch (mode_) { - case READ: - UpdateTransactionPattern(PATTERN_ENTRY_USED); - result = BeginCacheRead(); - break; - case READ_WRITE: - result = BeginPartialCacheValidation(); - break; - case UPDATE: - result = BeginExternallyConditionalizedRequest(); - break; - case WRITE: - default: - NOTREACHED(); - } - return result; -} - -int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch() { - // Write back the toggled value for the next use of this entry. - response_.unused_since_prefetch = !response_.unused_since_prefetch; - - // TODO(jkarlin): If DoUpdateCachedResponse is also called for this - // transaction then metadata will be written to cache twice. If prefetching - // becomes more common, consider combining the writes. - target_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE; - next_state_ = STATE_CACHE_WRITE_RESPONSE; - return OK; -} - -int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete( - int result) { - // Restore the original value for this transaction. - response_.unused_since_prefetch = !response_.unused_since_prefetch; - next_state_ = STATE_CACHE_DISPATCH_VALIDATION; - return OK; -} - -int HttpCache::Transaction::DoCacheWriteResponse() { - // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. - tracked_objects::ScopedTracker tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "422516 HttpCache::Transaction::DoCacheWriteResponse")); - - if (entry_) { - if (net_log_.IsCapturing()) - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); - } - return WriteResponseInfoToEntry(false); -} - -int HttpCache::Transaction::DoCacheWriteTruncatedResponse() { - if (entry_) { - if (net_log_.IsCapturing()) - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); - } - return WriteResponseInfoToEntry(true); -} - -int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { - next_state_ = target_state_; - target_state_ = STATE_NONE; - if (!entry_) - return OK; - if (net_log_.IsCapturing()) { - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, - result); - } - - // Balance the AddRef from WriteResponseInfoToEntry. - if (result != io_buf_len_) { - DLOG(ERROR) << "failed to write response info to cache"; - DoneWritingToEntry(false); - } - return OK; -} - int HttpCache::Transaction::DoCacheReadMetadata() { DCHECK(entry_); DCHECK(!response_.metadata.get()); @@ -1795,26 +1788,36 @@ int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) { return OK; } -int HttpCache::Transaction::DoCacheQueryData() { - next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE; - return entry_->disk_entry->ReadyForSparseIO(io_callback_); +int HttpCache::Transaction::DoNetworkRead() { + next_state_ = STATE_NETWORK_READ_COMPLETE; + return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_); } -int HttpCache::Transaction::DoCacheQueryDataComplete(int result) { - DCHECK_EQ(OK, result); +int HttpCache::Transaction::DoNetworkReadComplete(int result) { + DCHECK(mode_ & WRITE || mode_ == NONE); + if (!cache_.get()) return ERR_UNEXPECTED; - return ValidateEntryHeadersAndContinue(); + // If there is an error or we aren't saving the data, we are done; just wait + // until the destructor runs to see if we can keep the data. + if (mode_ == NONE || result < 0) + return result; + + next_state_ = STATE_CACHE_WRITE_DATA; + return result; } int HttpCache::Transaction::DoCacheReadData() { + if (request_->method == "HEAD") + return 0; + DCHECK(entry_); next_state_ = STATE_CACHE_READ_DATA_COMPLETE; if (net_log_.IsCapturing()) net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA); - if (partial_.get()) { + if (partial_) { return partial_->CacheRead(entry_->disk_entry, read_buf_.get(), io_buf_len_, io_callback_); } @@ -1833,7 +1836,7 @@ int HttpCache::Transaction::DoCacheReadDataComplete(int result) { if (!cache_.get()) return ERR_UNEXPECTED; - if (partial_.get()) { + if (partial_) { // Partial requests are confusing to report in histograms because they may // have multiple underlying requests. UpdateTransactionPattern(PATTERN_NOT_COVERED); @@ -1875,7 +1878,6 @@ int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { result); } } - // Balance the AddRef from DoCacheWriteData. if (!cache_.get()) return ERR_UNEXPECTED; @@ -1886,31 +1888,42 @@ int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { // We want to ignore errors writing to disk and just keep reading from // the network. result = write_len_; - } else if (!done_reading_ && entry_) { + } else if (!done_reading_ && entry_ && (!partial_ || truncated_)) { int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); int64 body_size = response_.headers->GetContentLength(); if (body_size >= 0 && body_size <= current_size) done_reading_ = true; } - if (partial_.get()) { + if (partial_) { // This may be the last request. - if (!(result == 0 && !truncated_ && - (partial_->IsLastRange() || mode_ == WRITE))) + if (result != 0 || truncated_ || + !(partial_->IsLastRange() || mode_ == WRITE)) { return DoPartialNetworkReadCompleted(result); + } } if (result == 0) { // End of file. This may be the result of a connection problem so see if we // have to keep the entry around to be flagged as truncated later on. - if (done_reading_ || !entry_ || partial_.get() || - response_.headers->GetContentLength() <= 0) + if (done_reading_ || !entry_ || partial_ || + response_.headers->GetContentLength() <= 0) { DoneWritingToEntry(true); + } } return result; } +int HttpCache::Transaction::DoCacheWriteTruncatedResponse() { + next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE; + return WriteResponseInfoToEntry(true); +} + +int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) { + return OnWriteResponseInfoToEntryComplete(result); +} + //----------------------------------------------------------------------------- void HttpCache::Transaction::ReadCertChain() { @@ -2098,7 +2111,7 @@ bool HttpCache::Transaction::ShouldPassThrough() { int HttpCache::Transaction::BeginCacheRead() { // We don't support any combination of LOAD_ONLY_FROM_CACHE and byte ranges. - if (response_.headers->response_code() == 206 || partial_.get()) { + if (response_.headers->response_code() == 206 || partial_) { NOTREACHED(); return ERR_CACHE_MISS; } @@ -2117,12 +2130,19 @@ int HttpCache::Transaction::BeginCacheRead() { } int HttpCache::Transaction::BeginCacheValidation() { - DCHECK(mode_ == READ_WRITE); + DCHECK_EQ(mode_, READ_WRITE); ValidationType required_validation = RequiresValidation(); bool skip_validation = (required_validation == VALIDATION_NONE); + if ((effective_load_flags_ & LOAD_SUPPORT_ASYNC_REVALIDATION) && + required_validation == VALIDATION_ASYNCHRONOUS) { + DCHECK_EQ(request_->method, "GET"); + skip_validation = true; + response_.async_revalidation_required = true; + } + if (request_->method == "HEAD" && (truncated_ || response_.headers->response_code() == 206)) { DCHECK(!partial_); @@ -2142,7 +2162,7 @@ int HttpCache::Transaction::BeginCacheValidation() { skip_validation = !partial_->initial_validation(); } - if (partial_.get() && (is_sparse_ || truncated_) && + if (partial_ && (is_sparse_ || truncated_) && (!partial_->IsCurrentRangeCached() || invalid_range_)) { // Force revalidation for sparse or truncated entries. Note that we don't // want to ignore the regular validation logic just because a byte range was @@ -2163,7 +2183,7 @@ int HttpCache::Transaction::BeginCacheValidation() { if (!ConditionalizeRequest()) { couldnt_conditionalize_request_ = true; UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE); - if (partial_.get()) + if (partial_) return DoRestartPartialRequest(); DCHECK_NE(206, response_.headers->response_code()); @@ -2174,38 +2194,34 @@ int HttpCache::Transaction::BeginCacheValidation() { } int HttpCache::Transaction::BeginPartialCacheValidation() { - DCHECK(mode_ == READ_WRITE); + DCHECK_EQ(mode_, READ_WRITE); - if (response_.headers->response_code() != 206 && !partial_.get() && - !truncated_) { + if (response_.headers->response_code() != 206 && !partial_ && !truncated_) return BeginCacheValidation(); - } // Partial requests should not be recorded in histograms. UpdateTransactionPattern(PATTERN_NOT_COVERED); - if (range_requested_) { - next_state_ = STATE_CACHE_QUERY_DATA; - return OK; - } - - // The request is not for a range, but we have stored just ranges. - if (request_->method == "HEAD") return BeginCacheValidation(); - partial_.reset(new PartialData()); - partial_->SetHeaders(request_->extra_headers); - if (!custom_request_.get()) { - custom_request_.reset(new HttpRequestInfo(*request_)); - request_ = custom_request_.get(); + if (!range_requested_) { + // The request is not for a range, but we have stored just ranges. + + partial_.reset(new PartialData()); + partial_->SetHeaders(request_->extra_headers); + if (!custom_request_.get()) { + custom_request_.reset(new HttpRequestInfo(*request_)); + request_ = custom_request_.get(); + } } - return ValidateEntryHeadersAndContinue(); + next_state_ = STATE_CACHE_QUERY_DATA; + return OK; } // This should only be called once per request. int HttpCache::Transaction::ValidateEntryHeadersAndContinue() { - DCHECK(mode_ == READ_WRITE); + DCHECK_EQ(mode_, READ_WRITE); if (!partial_->UpdateFromStoredHeaders( response_.headers.get(), entry_->disk_entry, truncated_)) { @@ -2254,7 +2270,7 @@ int HttpCache::Transaction::BeginExternallyConditionalizedRequest() { EXTERNALLY_CONDITIONALIZED_CACHE_USABLE; if (mode_ == NONE) type = EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS; - else if (RequiresValidation()) + else if (RequiresValidation() != VALIDATION_NONE) type = EXTERNALLY_CONDITIONALIZED_CACHE_REQUIRES_VALIDATION; // TODO(ricea): Add CACHE_USABLE_STALE once stale-while-revalidate CL landed. @@ -2384,15 +2400,15 @@ bool HttpCache::Transaction::ConditionalizeRequest() { if (etag_value.empty() && last_modified_value.empty()) return false; - if (!partial_.get()) { + if (!partial_) { // Need to customize the request, so this forces us to allocate :( custom_request_.reset(new HttpRequestInfo(*request_)); request_ = custom_request_.get(); } DCHECK(custom_request_.get()); - bool use_if_range = partial_.get() && !partial_->IsCurrentRangeCached() && - !invalid_range_; + bool use_if_range = + partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_; if (!use_if_range) { // stale-while-revalidate is not useful when we only have a partial response @@ -2426,7 +2442,7 @@ bool HttpCache::Transaction::ConditionalizeRequest() { } // For byte-range requests, make sure that we use only one way to validate // the request. - if (partial_.get() && !partial_->IsCurrentRangeCached()) + if (partial_ && !partial_->IsCurrentRangeCached()) return true; } @@ -2490,7 +2506,7 @@ bool HttpCache::Transaction::ValidatePartialResponse() { return true; } - if (!partial_.get()) { + if (!partial_) { // We are not expecting 206 but we may have one. if (partial_response) IgnoreRangeRequest(); @@ -2591,7 +2607,7 @@ void HttpCache::Transaction::FixHeadersForHead() { int HttpCache::Transaction::SetupEntryForRead() { if (network_trans_) ResetNetworkTransaction(); - if (partial_.get()) { + if (partial_) { if (truncated_ || is_sparse_ || !invalid_range_) { // We are going to return the saved response headers to the caller, so // we may need to adjust them first. @@ -2612,24 +2628,6 @@ int HttpCache::Transaction::SetupEntryForRead() { return OK; } - -int HttpCache::Transaction::ReadFromNetwork(IOBuffer* data, int data_len) { - read_buf_ = data; - io_buf_len_ = data_len; - next_state_ = STATE_NETWORK_READ; - return DoLoop(OK); -} - -int HttpCache::Transaction::ReadFromEntry(IOBuffer* data, int data_len) { - if (request_->method == "HEAD") - return 0; - - read_buf_ = data; - io_buf_len_ = data_len; - next_state_ = STATE_CACHE_READ_DATA; - return DoLoop(OK); -} - int HttpCache::Transaction::WriteToEntry(int index, int offset, IOBuffer* data, int data_len, const CompletionCallback& callback) { @@ -2637,7 +2635,7 @@ int HttpCache::Transaction::WriteToEntry(int index, int offset, return data_len; int rv = 0; - if (!partial_.get() || !data_len) { + if (!partial_ || !data_len) { rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback, true); } else { @@ -2647,10 +2645,12 @@ int HttpCache::Transaction::WriteToEntry(int index, int offset, } int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { - next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; if (!entry_) return OK; + if (net_log_.IsCapturing()) + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); + // Do not cache no-store content. Do not cache content with cert errors // either. This is to prevent not reporting net errors when loading a // resource from the cache. When we load a page over HTTPS with a cert error @@ -2686,6 +2686,21 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { io_buf_len_, io_callback_, true); } +int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { + if (!entry_) + return OK; + if (net_log_.IsCapturing()) { + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, + result); + } + + if (result != io_buf_len_) { + DLOG(ERROR) << "failed to write response info to cache"; + DoneWritingToEntry(false); + } + return OK; +} + void HttpCache::Transaction::DoneWritingToEntry(bool success) { if (!entry_) return; @@ -2807,10 +2822,13 @@ void HttpCache::Transaction::ResetNetworkTransaction() { if (network_trans_->GetLoadTimingInfo(&load_timing)) old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing)); total_received_bytes_ += network_trans_->GetTotalReceivedBytes(); + total_sent_bytes_ += network_trans_->GetTotalSentBytes(); ConnectionAttempts attempts; network_trans_->GetConnectionAttempts(&attempts); for (const auto& attempt : attempts) old_connection_attempts_.push_back(attempt); + old_remote_endpoint_ = IPEndPoint(); + network_trans_->GetRemoteEndpoint(&old_remote_endpoint_); network_trans_.reset(); } diff --git a/chromium/net/http/http_cache_transaction.h b/chromium/net/http/http_cache_transaction.h index 9b151af37eb..482bb644977 100644 --- a/chromium/net/http/http_cache_transaction.h +++ b/chromium/net/http/http_cache_transaction.h @@ -9,6 +9,7 @@ #define NET_HTTP_HTTP_CACHE_TRANSACTION_H_ #include <stddef.h> +#include <stdint.h> #include <string> @@ -19,6 +20,7 @@ #include "base/time/time.h" #include "net/base/completion_callback.h" #include "net/base/io_buffer.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_states.h" #include "net/base/request_priority.h" #include "net/base/upload_progress.h" @@ -141,13 +143,15 @@ class HttpCache::Transaction : public HttpTransaction { const CompletionCallback& callback) override; void StopCaching() override; bool GetFullRequestHeaders(HttpRequestHeaders* headers) const override; - int64 GetTotalReceivedBytes() const override; + int64_t GetTotalReceivedBytes() const override; + int64_t GetTotalSentBytes() const override; void DoneReading() override; const HttpResponseInfo* GetResponseInfo() const override; LoadState GetLoadState() const override; UploadProgress GetUploadProgress(void) const override; void SetQuicServerInfo(QuicServerInfo* quic_server_info) override; bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; + bool GetRemoteEndpoint(IPEndPoint* endpoint) const override; void SetPriority(RequestPriority priority) override; void SetWebSocketHandshakeStreamCreateHelper( WebSocketHandshakeStreamBase::CreateHelper* create_helper) override; @@ -170,49 +174,55 @@ class HttpCache::Transaction : public HttpTransaction { }; enum State { + // Normally, states are traversed in approximately this order. STATE_NONE, STATE_GET_BACKEND, STATE_GET_BACKEND_COMPLETE, - STATE_SEND_REQUEST, - STATE_SEND_REQUEST_COMPLETE, - STATE_SUCCESSFUL_SEND_REQUEST, - STATE_NETWORK_READ, - STATE_NETWORK_READ_COMPLETE, STATE_INIT_ENTRY, STATE_OPEN_ENTRY, STATE_OPEN_ENTRY_COMPLETE, - STATE_CREATE_ENTRY, - STATE_CREATE_ENTRY_COMPLETE, STATE_DOOM_ENTRY, STATE_DOOM_ENTRY_COMPLETE, + STATE_CREATE_ENTRY, + STATE_CREATE_ENTRY_COMPLETE, STATE_ADD_TO_ENTRY, STATE_ADD_TO_ENTRY_COMPLETE, + STATE_CACHE_READ_RESPONSE, + STATE_CACHE_READ_RESPONSE_COMPLETE, + STATE_TOGGLE_UNUSED_SINCE_PREFETCH, + STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE, + STATE_CACHE_DISPATCH_VALIDATION, + STATE_CACHE_QUERY_DATA, + STATE_CACHE_QUERY_DATA_COMPLETE, STATE_START_PARTIAL_CACHE_VALIDATION, STATE_COMPLETE_PARTIAL_CACHE_VALIDATION, + STATE_SEND_REQUEST, + STATE_SEND_REQUEST_COMPLETE, + STATE_SUCCESSFUL_SEND_REQUEST, STATE_UPDATE_CACHED_RESPONSE, + STATE_CACHE_WRITE_UPDATED_RESPONSE, + STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE, STATE_UPDATE_CACHED_RESPONSE_COMPLETE, STATE_OVERWRITE_CACHED_RESPONSE, + STATE_CACHE_WRITE_RESPONSE, + STATE_CACHE_WRITE_RESPONSE_COMPLETE, STATE_TRUNCATE_CACHED_DATA, STATE_TRUNCATE_CACHED_DATA_COMPLETE, STATE_TRUNCATE_CACHED_METADATA, STATE_TRUNCATE_CACHED_METADATA_COMPLETE, STATE_PARTIAL_HEADERS_RECEIVED, - STATE_CACHE_READ_RESPONSE, - STATE_CACHE_READ_RESPONSE_COMPLETE, - STATE_CACHE_DISPATCH_VALIDATION, - STATE_TOGGLE_UNUSED_SINCE_PREFETCH, - STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE, - STATE_CACHE_WRITE_RESPONSE, - STATE_CACHE_WRITE_TRUNCATED_RESPONSE, - STATE_CACHE_WRITE_RESPONSE_COMPLETE, STATE_CACHE_READ_METADATA, STATE_CACHE_READ_METADATA_COMPLETE, - STATE_CACHE_QUERY_DATA, - STATE_CACHE_QUERY_DATA_COMPLETE, + + // These states are entered from Read/AddTruncatedFlag. + STATE_NETWORK_READ, + STATE_NETWORK_READ_COMPLETE, STATE_CACHE_READ_DATA, STATE_CACHE_READ_DATA_COMPLETE, STATE_CACHE_WRITE_DATA, - STATE_CACHE_WRITE_DATA_COMPLETE + STATE_CACHE_WRITE_DATA_COMPLETE, + STATE_CACHE_WRITE_TRUNCATED_RESPONSE, + STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE }; // Used for categorizing transactions for reporting in histograms. Patterns @@ -232,14 +242,8 @@ class HttpCache::Transaction : public HttpTransaction { PATTERN_MAX, }; - // This is a helper function used to trigger a completion callback. It may - // only be called if callback_ is non-null. - void DoCallback(int rv); - - // This will trigger the completion callback if appropriate. - int HandleResult(int rv); - - // Runs the state transition loop. + // Runs the state transition loop. Resets and calls |callback_| on exit, + // unless the return value is ERR_IO_PENDING. int DoLoop(int result); // Each of these methods corresponds to a State value. If there is an @@ -247,46 +251,49 @@ class HttpCache::Transaction : public HttpTransaction { // corresponding callback. int DoGetBackend(); int DoGetBackendComplete(int result); - int DoSendRequest(); - int DoSendRequestComplete(int result); - int DoSuccessfulSendRequest(); - int DoNetworkRead(); - int DoNetworkReadComplete(int result); int DoInitEntry(); int DoOpenEntry(); int DoOpenEntryComplete(int result); - int DoCreateEntry(); - int DoCreateEntryComplete(int result); int DoDoomEntry(); int DoDoomEntryComplete(int result); + int DoCreateEntry(); + int DoCreateEntryComplete(int result); int DoAddToEntry(); int DoAddToEntryComplete(int result); + int DoCacheReadResponse(); + int DoCacheReadResponseComplete(int result); + int DoCacheToggleUnusedSincePrefetch(); + int DoCacheToggleUnusedSincePrefetchComplete(int result); + int DoCacheDispatchValidation(); + int DoCacheQueryData(); + int DoCacheQueryDataComplete(int result); int DoStartPartialCacheValidation(); int DoCompletePartialCacheValidation(int result); + int DoSendRequest(); + int DoSendRequestComplete(int result); + int DoSuccessfulSendRequest(); int DoUpdateCachedResponse(); + int DoCacheWriteUpdatedResponse(); + int DoCacheWriteUpdatedResponseComplete(int result); int DoUpdateCachedResponseComplete(int result); int DoOverwriteCachedResponse(); + int DoCacheWriteResponse(); + int DoCacheWriteResponseComplete(int result); int DoTruncateCachedData(); int DoTruncateCachedDataComplete(int result); int DoTruncateCachedMetadata(); int DoTruncateCachedMetadataComplete(int result); int DoPartialHeadersReceived(); - int DoCacheReadResponse(); - int DoCacheReadResponseComplete(int result); - int DoCacheDispatchValidation(); - int DoCacheToggleUnusedSincePrefetch(); - int DoCacheToggleUnusedSincePrefetchComplete(int result); - int DoCacheWriteResponse(); - int DoCacheWriteTruncatedResponse(); - int DoCacheWriteResponseComplete(int result); int DoCacheReadMetadata(); int DoCacheReadMetadataComplete(int result); - int DoCacheQueryData(); - int DoCacheQueryDataComplete(int result); + int DoNetworkRead(); + int DoNetworkReadComplete(int result); int DoCacheReadData(); int DoCacheReadDataComplete(int result); int DoCacheWriteData(int num_bytes); int DoCacheWriteDataComplete(int result); + int DoCacheWriteTruncatedResponse(); + int DoCacheWriteTruncatedResponseComplete(int result); // These functions are involved in a field trial testing storing certificates // in seperate entries from the HttpResponseInfo. @@ -354,12 +361,6 @@ class HttpCache::Transaction : public HttpTransaction { // Setups the transaction for reading from the cache entry. int SetupEntryForRead(); - // Reads data from the network. - int ReadFromNetwork(IOBuffer* data, int data_len); - - // Reads data from the cache entry. - int ReadFromEntry(IOBuffer* data, int data_len); - // Called to write data to the cache entry. If the write fails, then the // cache entry is destroyed. Future calls to this function will just do // nothing without side-effect. Returns a network error code. @@ -370,6 +371,14 @@ class HttpCache::Transaction : public HttpTransaction { // entry should be marked as incomplete. int WriteResponseInfoToEntry(bool truncated); + // Helper function, should be called with result of WriteResponseInfoToEntry + // (or the result of the callback, when WriteResponseInfoToEntry returns + // ERR_IO_PENDING). Calls DoneWritingToEntry if |result| is not the right + // number of bytes. It is expected that the state that calls this will + // return whatever net error code this function returns, which currently + // is always "OK". + int OnWriteResponseInfoToEntryComplete(int result); + // Called when we are done writing to the cache entry. void DoneWritingToEntry(bool success); @@ -436,7 +445,6 @@ class HttpCache::Transaction : public HttpTransaction { const HttpResponseInfo* new_response_; std::string cache_key_; Mode mode_; - State target_state_; bool reading_; // We are already reading. Never reverts to false once set. bool invalid_range_; // We may bypass the cache for this request. bool truncated_; // We don't have all the response data. @@ -464,7 +472,8 @@ class HttpCache::Transaction : public HttpTransaction { base::TimeTicks first_cache_access_since_; base::TimeTicks send_request_since_; - int64 total_received_bytes_; + int64_t total_received_bytes_; + int64_t total_sent_bytes_; // Load timing information for the last network request, if any. Set in the // 304 and 206 response cases, as the network transaction may be destroyed @@ -472,6 +481,7 @@ class HttpCache::Transaction : public HttpTransaction { scoped_ptr<LoadTimingInfo> old_network_trans_load_timing_; ConnectionAttempts old_connection_attempts_; + IPEndPoint old_remote_endpoint_; // The helper object to use to create WebSocketHandshakeStreamBase // objects. Only relevant when establishing a WebSocket connection. diff --git a/chromium/net/http/http_cache_unittest.cc b/chromium/net/http/http_cache_unittest.cc index f490444356f..6eeef8f1157 100644 --- a/chromium/net/http/http_cache_unittest.cc +++ b/chromium/net/http/http_cache_unittest.cc @@ -4,6 +4,8 @@ #include "net/http/http_cache.h" +#include <stdint.h> + #include <algorithm> #include "base/bind.h" @@ -17,6 +19,7 @@ #include "net/base/cache_type.h" #include "net/base/elements_upload_data_stream.h" #include "net/base/host_port_pair.h" +#include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/base/load_timing_info.h" #include "net/base/load_timing_info_test_util.h" @@ -136,7 +139,9 @@ void RunTransactionTestBase(HttpCache* cache, HttpResponseInfo* response_info, const BoundNetLog& net_log, LoadTimingInfo* load_timing_info, - int64* received_bytes) { + int64_t* sent_bytes, + int64_t* received_bytes, + IPEndPoint* remote_endpoint) { TestCompletionCallback callback; // write to the cache @@ -168,8 +173,13 @@ void RunTransactionTestBase(HttpCache* cache, trans->GetLoadTimingInfo(load_timing_info); } + if (remote_endpoint) + ASSERT_TRUE(trans->GetRemoteEndpoint(remote_endpoint)); + ReadAndVerifyTransaction(trans.get(), trans_info); + if (sent_bytes) + *sent_bytes = trans->GetTotalSentBytes(); if (received_bytes) *received_bytes = trans->GetTotalReceivedBytes(); } @@ -179,7 +189,7 @@ void RunTransactionTestWithRequest(HttpCache* cache, const MockHttpRequest& request, HttpResponseInfo* response_info) { RunTransactionTestBase(cache, trans_info, request, response_info, - BoundNetLog(), NULL, NULL); + BoundNetLog(), nullptr, nullptr, nullptr, nullptr); } void RunTransactionTestAndGetTiming(HttpCache* cache, @@ -187,17 +197,29 @@ void RunTransactionTestAndGetTiming(HttpCache* cache, const BoundNetLog& log, LoadTimingInfo* load_timing_info) { RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info), - NULL, log, load_timing_info, NULL); + nullptr, log, load_timing_info, nullptr, nullptr, + nullptr); +} + +void RunTransactionTestAndGetTimingAndConnectedSocketAddress( + HttpCache* cache, + const MockTransaction& trans_info, + const BoundNetLog& log, + LoadTimingInfo* load_timing_info, + IPEndPoint* remote_endpoint) { + RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info), + nullptr, log, load_timing_info, nullptr, nullptr, + remote_endpoint); } void RunTransactionTest(HttpCache* cache, const MockTransaction& trans_info) { - RunTransactionTestAndGetTiming(cache, trans_info, BoundNetLog(), NULL); + RunTransactionTestAndGetTiming(cache, trans_info, BoundNetLog(), nullptr); } void RunTransactionTestWithLog(HttpCache* cache, const MockTransaction& trans_info, const BoundNetLog& log) { - RunTransactionTestAndGetTiming(cache, trans_info, log, NULL); + RunTransactionTestAndGetTiming(cache, trans_info, log, nullptr); } void RunTransactionTestWithResponseInfo(HttpCache* cache, @@ -214,7 +236,8 @@ void RunTransactionTestWithResponseInfoAndGetTiming( const BoundNetLog& log, LoadTimingInfo* load_timing_info) { RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info), - response, log, load_timing_info, NULL); + response, log, load_timing_info, nullptr, nullptr, + nullptr); } void RunTransactionTestWithResponse(HttpCache* cache, @@ -233,7 +256,8 @@ void RunTransactionTestWithResponseAndGetTiming( LoadTimingInfo* load_timing_info) { HttpResponseInfo response; RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info), - &response, log, load_timing_info, NULL); + &response, log, load_timing_info, nullptr, nullptr, + nullptr); response.headers->GetNormalizedHeaders(response_headers); } @@ -458,7 +482,7 @@ const char kFullRangeData[] = // Verifies the response headers (|response|) match a partial content // response for the range starting at |start| and ending at |end|. -void Verify206Response(std::string response, int start, int end) { +void Verify206Response(const std::string& response, int start, int end) { std::string raw_headers( HttpUtil::AssembleRawHeaders(response.data(), response.size())); scoped_refptr<HttpResponseHeaders> headers( @@ -503,6 +527,24 @@ void CreateTruncatedEntry(std::string raw_headers, MockHttpCache* cache) { entry->Close(); } +// Verifies that there's an entry with this |key| with the truncated flag set to +// |flag_value|, and with an optional |data_size| (if not zero). +void VerifyTruncatedFlag(MockHttpCache* cache, + const std::string& key, + bool flag_value, + int data_size) { + disk_cache::Entry* entry; + ASSERT_TRUE(cache->OpenBackendEntry(key, &entry)); + disk_cache::ScopedEntryPtr closer(entry); + + HttpResponseInfo response; + bool truncated = !flag_value; + EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); + EXPECT_EQ(flag_value, truncated); + if (data_size) + EXPECT_EQ(data_size, entry->GetDataSize(1)); +} + // Helper to represent a network HTTP response. struct Response { // Set this response into |trans|. @@ -1909,7 +1951,14 @@ TEST(HttpCache, DeleteCacheWaitingForBackend2) { EXPECT_FALSE(cb2.have_result()); } -TEST(HttpCache, TypicalGET_ConditionalRequest) { +// Fails only on bots. crbug.com/533640 +#if defined(OS_ANDROID) +#define MAYBE_TypicalGET_ConditionalRequest \ + DISABLED_TypicalGET_ConditionalRequest +#else +#define MAYBE_TypicalGET_ConditionalRequest TypicalGET_ConditionalRequest +#endif +TEST(HttpCache, MAYBE_TypicalGET_ConditionalRequest) { MockHttpCache cache; // write to the cache @@ -1961,13 +2010,17 @@ TEST(HttpCache, ETagGET_ConditionalRequest_304) { transaction.handler = ETagGet_ConditionalRequest_Handler; BoundTestNetLog log; LoadTimingInfo load_timing_info; - RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(), - &load_timing_info); + IPEndPoint remote_endpoint; + RunTransactionTestAndGetTimingAndConnectedSocketAddress( + cache.http_cache(), transaction, log.bound(), &load_timing_info, + &remote_endpoint); EXPECT_EQ(2, cache.network_layer()->transaction_count()); EXPECT_EQ(1, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); TestLoadTimingNetworkRequest(load_timing_info); + + EXPECT_FALSE(remote_endpoint.address().empty()); } class RevalidationServer { @@ -3985,9 +4038,15 @@ TEST(HttpCache, RangeGET_NoContentLength) { RemoveMockTransaction(&transaction); } +// Fails only on bots. crbug.com/533640 +#if defined(OS_ANDROID) +#define MAYBE_RangeGET_OK DISABLED_RangeGET_OK +#else +#define MAYBE_RangeGET_OK RangeGET_OK +#endif // Tests that we can cache range requests and fetch random blocks from the // cache and the network. -TEST(HttpCache, RangeGET_OK) { +TEST(HttpCache, MAYBE_RangeGET_OK) { MockHttpCache cache; AddMockTransaction(&kRangeGET_TransactionOK); std::string headers; @@ -4045,9 +4104,15 @@ TEST(HttpCache, RangeGET_OK) { RemoveMockTransaction(&kRangeGET_TransactionOK); } +// Fails only on bots. crbug.com/533640 +#if defined(OS_ANDROID) +#define MAYBE_RangeGET_SyncOK DISABLED_RangeGET_SyncOK +#else +#define MAYBE_RangeGET_SyncOK RangeGET_SyncOK +#endif // Tests that we can cache range requests and fetch random blocks from the // cache and the network, with synchronous responses. -TEST(HttpCache, RangeGET_SyncOK) { +TEST(HttpCache, MAYBE_RangeGET_SyncOK) { MockHttpCache cache; MockTransaction transaction(kRangeGET_TransactionOK); @@ -4105,6 +4170,34 @@ TEST(HttpCache, RangeGET_SyncOK) { RemoveMockTransaction(&transaction); } +// Tests that if the previous transaction is cancelled while busy (doing sparse +// IO), a new transaction (that reuses that same ActiveEntry) waits until the +// entry is ready again. +TEST(HttpCache, Sparse_WaitForEntry) { + MockHttpCache cache; + + ScopedMockTransaction transaction(kRangeGET_TransactionOK); + + // Create a sparse entry. + RunTransactionTest(cache.http_cache(), transaction); + + // Simulate a previous transaction being cancelled. + disk_cache::Entry* entry; + ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); + entry->CancelSparseIO(); + + // Test with a range request. + RunTransactionTest(cache.http_cache(), transaction); + + // Now test with a regular request. + entry->CancelSparseIO(); + transaction.request_headers = EXTRA_HEADER; + transaction.data = kFullRangeData; + RunTransactionTest(cache.http_cache(), transaction); + + entry->Close(); +} + // Tests that we don't revalidate an entry unless we are required to do so. TEST(HttpCache, RangeGET_Revalidate1) { MockHttpCache cache; @@ -4154,8 +4247,14 @@ TEST(HttpCache, RangeGET_Revalidate1) { RemoveMockTransaction(&transaction); } +// Fails only on bots. crbug.com/533640 +#if defined(OS_ANDROID) +#define MAYBE_RangeGET_Revalidate2 DISABLED_RangeGET_Revalidate2 +#else +#define MAYBE_RangeGET_Revalidate2 RangeGET_Revalidate2 +#endif // Checks that we revalidate an entry when the headers say so. -TEST(HttpCache, RangeGET_Revalidate2) { +TEST(HttpCache, MAYBE_RangeGET_Revalidate2) { MockHttpCache cache; std::string headers; @@ -4886,8 +4985,14 @@ TEST(HttpCache, GET_Previous206_NotValidation) { EXPECT_EQ(2, cache.disk_cache()->create_count()); } +// Fails only on bots. crbug.com/533640 +#if defined(OS_ANDROID) +#define MAYBE_RangeGET_Previous200 DISABLED_RangeGET_Previous200 +#else +#define MAYBE_RangeGET_Previous200 RangeGET_Previous200 +#endif // Tests that we can handle range requests with cached 200 responses. -TEST(HttpCache, RangeGET_Previous200) { +TEST(HttpCache, MAYBE_RangeGET_Previous200) { MockHttpCache cache; // Store the whole thing with status 200. @@ -5028,8 +5133,14 @@ TEST(HttpCache, RangeGET_MoreThanCurrentSize) { RemoveMockTransaction(&kRangeGET_TransactionOK); } +// Fails only on bots. crbug.com/533640 +#if defined(OS_ANDROID) +#define MAYBE_RangeGET_Cancel DISABLED_RangeGET_Cancel +#else +#define MAYBE_RangeGET_Cancel RangeGET_Cancel +#endif // Tests that we don't delete a sparse entry when we cancel a request. -TEST(HttpCache, RangeGET_Cancel) { +TEST(HttpCache, MAYBE_RangeGET_Cancel) { MockHttpCache cache; AddMockTransaction(&kRangeGET_TransactionOK); @@ -5064,9 +5175,15 @@ TEST(HttpCache, RangeGET_Cancel) { RemoveMockTransaction(&kRangeGET_TransactionOK); } +// Fails only on bots. crbug.com/533640 +#if defined(OS_ANDROID) +#define MAYBE_RangeGET_Cancel2 DISABLED_RangeGET_Cancel2 +#else +#define MAYBE_RangeGET_Cancel2 RangeGET_Cancel2 +#endif // Tests that we don't delete a sparse entry when we start a new request after // cancelling the previous one. -TEST(HttpCache, RangeGET_Cancel2) { +TEST(HttpCache, MAYBE_RangeGET_Cancel2) { MockHttpCache cache; AddMockTransaction(&kRangeGET_TransactionOK); @@ -5606,12 +5723,11 @@ TEST(HttpCache, DoomOnDestruction3) { TEST(HttpCache, SetTruncatedFlag) { MockHttpCache cache; - MockTransaction transaction(kSimpleGET_Transaction); + ScopedMockTransaction transaction(kSimpleGET_Transaction); transaction.response_headers = "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n" "Content-Length: 22\n" "Etag: \"foopy\"\n"; - AddMockTransaction(&transaction); MockHttpRequest request(transaction); scoped_ptr<Context> c(new Context()); @@ -5653,27 +5769,18 @@ TEST(HttpCache, SetTruncatedFlag) { EXPECT_FALSE(c->callback.have_result()); // Verify that the entry is marked as incomplete. - disk_cache::Entry* entry; - ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); - HttpResponseInfo response; - bool truncated = false; - EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); - EXPECT_TRUE(truncated); - entry->Close(); - - RemoveMockTransaction(&transaction); + VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, true, 0); } // Tests that we don't mark an entry as truncated when we read everything. TEST(HttpCache, DontSetTruncatedFlag) { MockHttpCache cache; - MockTransaction transaction(kSimpleGET_Transaction); + ScopedMockTransaction transaction(kSimpleGET_Transaction); transaction.response_headers = "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n" "Content-Length: 22\n" "Etag: \"foopy\"\n"; - AddMockTransaction(&transaction); MockHttpRequest request(transaction); scoped_ptr<Context> c(new Context()); @@ -5692,21 +5799,66 @@ TEST(HttpCache, DontSetTruncatedFlag) { c->trans.reset(); // Verify that the entry is not marked as truncated. - disk_cache::Entry* entry; - ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); - HttpResponseInfo response; - bool truncated = true; - EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); - EXPECT_FALSE(truncated); - entry->Close(); + VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, false, 0); +} - RemoveMockTransaction(&transaction); +// Tests that sparse entries don't set the truncate flag. +TEST(HttpCache, RangeGET_DontTruncate) { + MockHttpCache cache; + + ScopedMockTransaction transaction(kRangeGET_TransactionOK); + transaction.request_headers = "Range: bytes = 0-19\r\n" EXTRA_HEADER; + + scoped_ptr<MockHttpRequest> request(new MockHttpRequest(transaction)); + scoped_ptr<HttpTransaction> trans; + + int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans); + EXPECT_EQ(OK, rv); + + TestCompletionCallback cb; + rv = trans->Start(request.get(), cb.callback(), BoundNetLog()); + EXPECT_EQ(0, cb.GetResult(rv)); + + scoped_refptr<IOBuffer> buf(new IOBuffer(10)); + rv = trans->Read(buf.get(), 10, cb.callback()); + EXPECT_EQ(10, cb.GetResult(rv)); + + // Should not trigger any DCHECK. + trans.reset(); + VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, false, 0); +} + +// Tests that sparse entries don't set the truncate flag (when the byte range +// starts after 0). +TEST(HttpCache, RangeGET_DontTruncate2) { + MockHttpCache cache; + + ScopedMockTransaction transaction(kRangeGET_TransactionOK); + transaction.request_headers = "Range: bytes = 30-49\r\n" EXTRA_HEADER; + + scoped_ptr<MockHttpRequest> request(new MockHttpRequest(transaction)); + scoped_ptr<HttpTransaction> trans; + + int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans); + EXPECT_EQ(OK, rv); + + TestCompletionCallback cb; + rv = trans->Start(request.get(), cb.callback(), BoundNetLog()); + EXPECT_EQ(0, cb.GetResult(rv)); + + scoped_refptr<IOBuffer> buf(new IOBuffer(10)); + rv = trans->Read(buf.get(), 10, cb.callback()); + EXPECT_EQ(10, cb.GetResult(rv)); + + // Should not trigger any DCHECK. + trans.reset(); + VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, false, 0); } // Tests that we can continue with a request that was interrupted. TEST(HttpCache, GET_IncompleteResource) { MockHttpCache cache; - AddMockTransaction(&kRangeGET_TransactionOK); + ScopedMockTransaction transaction(kRangeGET_TransactionOK); std::string raw_headers("HTTP/1.1 200 OK\n" "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" @@ -5717,7 +5869,6 @@ TEST(HttpCache, GET_IncompleteResource) { // Now make a regular request. std::string headers; - MockTransaction transaction(kRangeGET_TransactionOK); transaction.request_headers = EXTRA_HEADER; transaction.data = kFullRangeData; RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); @@ -5736,16 +5887,7 @@ TEST(HttpCache, GET_IncompleteResource) { EXPECT_EQ(1, cache.disk_cache()->create_count()); // Verify that the disk entry was updated. - disk_cache::Entry* entry; - ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); - EXPECT_EQ(80, entry->GetDataSize(1)); - bool truncated = true; - HttpResponseInfo response; - EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); - EXPECT_FALSE(truncated); - entry->Close(); - - RemoveMockTransaction(&kRangeGET_TransactionOK); + VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, false, 80); } // Tests the handling of no-store when revalidating a truncated entry. @@ -6011,7 +6153,7 @@ TEST(HttpCache, TransactionRetryLimit) { // Tests that we cache a 200 response to the validation request. TEST(HttpCache, GET_IncompleteResource4) { MockHttpCache cache; - AddMockTransaction(&kRangeGET_TransactionOK); + ScopedMockTransaction transaction(kRangeGET_TransactionOK); std::string raw_headers("HTTP/1.1 200 OK\n" "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n" @@ -6022,7 +6164,6 @@ TEST(HttpCache, GET_IncompleteResource4) { // Now make a regular request. std::string headers; - MockTransaction transaction(kRangeGET_TransactionOK); transaction.request_headers = EXTRA_HEADER; transaction.data = "Not a range"; RangeTransactionServer handler; @@ -6034,23 +6175,14 @@ TEST(HttpCache, GET_IncompleteResource4) { EXPECT_EQ(1, cache.disk_cache()->create_count()); // Verify that the disk entry was updated. - disk_cache::Entry* entry; - ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); - EXPECT_EQ(11, entry->GetDataSize(1)); - bool truncated = true; - HttpResponseInfo response; - EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); - EXPECT_FALSE(truncated); - entry->Close(); - - RemoveMockTransaction(&kRangeGET_TransactionOK); + VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, false, 11); } // Tests that when we cancel a request that was interrupted, we mark it again // as truncated. TEST(HttpCache, GET_CancelIncompleteResource) { MockHttpCache cache; - AddMockTransaction(&kRangeGET_TransactionOK); + ScopedMockTransaction transaction(kRangeGET_TransactionOK); std::string raw_headers("HTTP/1.1 200 OK\n" "Last-Modified: Sat, 18 Apr 2009 01:10:43 GMT\n" @@ -6060,7 +6192,6 @@ TEST(HttpCache, GET_CancelIncompleteResource) { CreateTruncatedEntry(raw_headers, &cache); // Now make a regular request. - MockTransaction transaction(kRangeGET_TransactionOK); transaction.request_headers = EXTRA_HEADER; MockHttpRequest request(transaction); @@ -6087,15 +6218,7 @@ TEST(HttpCache, GET_CancelIncompleteResource) { EXPECT_EQ(1, cache.disk_cache()->create_count()); // Verify that the disk entry was updated: now we have 30 bytes. - disk_cache::Entry* entry; - ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); - EXPECT_EQ(30, entry->GetDataSize(1)); - bool truncated = false; - HttpResponseInfo response; - EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); - EXPECT_TRUE(truncated); - entry->Close(); - RemoveMockTransaction(&kRangeGET_TransactionOK); + VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, true, 30); } // Tests that we can handle range requests when we have a truncated entry. @@ -6842,7 +6965,7 @@ TEST(HttpCache, StopCachingSavesEntry) { ASSERT_EQ(OK, cache.CreateTransaction(&trans)); // Force a response that can be resumed. - MockTransaction mock_transaction(kSimpleGET_Transaction); + ScopedMockTransaction mock_transaction(kSimpleGET_Transaction); AddMockTransaction(&mock_transaction); mock_transaction.response_headers = "Cache-Control: max-age=10000\n" "Content-Length: 42\n" @@ -6862,18 +6985,10 @@ TEST(HttpCache, StopCachingSavesEntry) { EXPECT_GT(callback.GetResult(rv), 0); rv = trans->Read(buf.get(), 256, callback.callback()); EXPECT_EQ(callback.GetResult(rv), 0); - - RemoveMockTransaction(&mock_transaction); } // Verify that the entry is marked as incomplete. - disk_cache::Entry* entry; - ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); - HttpResponseInfo response; - bool truncated = false; - EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); - EXPECT_TRUE(truncated); - entry->Close(); + VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, true, 0); } // Tests that we handle truncated enries when StopCaching is called. @@ -6917,15 +7032,7 @@ TEST(HttpCache, StopCachingTruncatedEntry) { } // Verify that the disk entry was updated. - disk_cache::Entry* entry; - ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); - EXPECT_EQ(80, entry->GetDataSize(1)); - bool truncated = true; - HttpResponseInfo response; - EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); - EXPECT_FALSE(truncated); - entry->Close(); - + VerifyTruncatedFlag(&cache, kRangeGET_TransactionOK.url, false, 80); RemoveMockTransaction(&kRangeGET_TransactionOK); } @@ -6965,13 +7072,7 @@ TEST(HttpCache, TruncatedByContentLength2) { RemoveMockTransaction(&transaction); // Verify that the entry is marked as incomplete. - disk_cache::Entry* entry; - ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); - HttpResponseInfo response; - bool truncated = false; - EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); - EXPECT_TRUE(truncated); - entry->Close(); + VerifyTruncatedFlag(&cache, kSimpleGET_Transaction.url, true, 0); } // Make sure that calling SetPriority on a cache transaction passes on @@ -7080,46 +7181,50 @@ TEST(HttpCache, SetPriorityNewTransaction) { RemoveMockTransaction(&kRangeGET_TransactionOK); } -int64 RunTransactionAndGetReceivedBytes( - MockHttpCache& cache, - const MockTransaction& trans_info) { - int64 received_bytes = -1; +namespace { + +void RunTransactionAndGetNetworkBytes(MockHttpCache& cache, + const MockTransaction& trans_info, + int64_t* sent_bytes, + int64_t* received_bytes) { RunTransactionTestBase(cache.http_cache(), trans_info, - MockHttpRequest(trans_info), NULL, BoundNetLog(), NULL, - &received_bytes); - return received_bytes; + MockHttpRequest(trans_info), nullptr, BoundNetLog(), + nullptr, sent_bytes, received_bytes, nullptr); } -int64 TransactionSize(const MockTransaction& transaction) { - return strlen(transaction.status) + strlen(transaction.response_headers) + - strlen(transaction.data); -} +} // namespace -TEST(HttpCache, ReceivedBytesCacheMissAndThenHit) { +TEST(HttpCache, NetworkBytesCacheMissAndThenHit) { MockHttpCache cache; MockTransaction transaction(kSimpleGET_Transaction); - int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); - EXPECT_EQ(TransactionSize(transaction), received_bytes); + int64_t sent, received; + RunTransactionAndGetNetworkBytes(cache, transaction, &sent, &received); + EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent); + EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received); - received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); - EXPECT_EQ(0, received_bytes); + RunTransactionAndGetNetworkBytes(cache, transaction, &sent, &received); + EXPECT_EQ(0, sent); + EXPECT_EQ(0, received); } -TEST(HttpCache, ReceivedBytesConditionalRequest304) { +TEST(HttpCache, NetworkBytesConditionalRequest304) { MockHttpCache cache; ScopedMockTransaction transaction(kETagGET_Transaction); - int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); - EXPECT_EQ(TransactionSize(transaction), received_bytes); + int64_t sent, received; + RunTransactionAndGetNetworkBytes(cache, transaction, &sent, &received); + EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent); + EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received); transaction.load_flags = LOAD_VALIDATE_CACHE; transaction.handler = ETagGet_ConditionalRequest_Handler; - received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); - EXPECT_EQ(TransactionSize(transaction), received_bytes); + RunTransactionAndGetNetworkBytes(cache, transaction, &sent, &received); + EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent); + EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received); } -TEST(HttpCache, ReceivedBytesConditionalRequest200) { +TEST(HttpCache, NetworkBytesConditionalRequest200) { MockHttpCache cache; MockTransaction transaction(kTypicalGET_Transaction); @@ -7131,45 +7236,52 @@ TEST(HttpCache, ReceivedBytesConditionalRequest200) { "Cache-Control: max-age=0\n" "Vary: Foo\n"; AddMockTransaction(&transaction); - int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); - EXPECT_EQ(TransactionSize(transaction), received_bytes); + int64_t sent, received; + RunTransactionAndGetNetworkBytes(cache, transaction, &sent, &received); + EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent); + EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received); RevalidationServer server; transaction.handler = server.Handler; transaction.request_headers = "Foo: none\r\n"; - received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); - EXPECT_EQ(TransactionSize(transaction), received_bytes); + RunTransactionAndGetNetworkBytes(cache, transaction, &sent, &received); + EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent); + EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received); RemoveMockTransaction(&transaction); } -TEST(HttpCache, ReceivedBytesRange) { +TEST(HttpCache, NetworkBytesRange) { MockHttpCache cache; AddMockTransaction(&kRangeGET_TransactionOK); MockTransaction transaction(kRangeGET_TransactionOK); // Read bytes 40-49 from the network. - int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); - int64 range_response_size = TransactionSize(transaction); - EXPECT_EQ(range_response_size, received_bytes); + int64_t sent, received; + RunTransactionAndGetNetworkBytes(cache, transaction, &sent, &received); + EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent); + EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received); // Read bytes 40-49 from the cache. - received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); - EXPECT_EQ(0, received_bytes); + RunTransactionAndGetNetworkBytes(cache, transaction, &sent, &received); + EXPECT_EQ(0, sent); + EXPECT_EQ(0, received); base::MessageLoop::current()->RunUntilIdle(); // Read bytes 30-39 from the network. transaction.request_headers = "Range: bytes = 30-39\r\n" EXTRA_HEADER; transaction.data = "rg: 30-39 "; - received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); - EXPECT_EQ(range_response_size, received_bytes); + RunTransactionAndGetNetworkBytes(cache, transaction, &sent, &received); + EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes, sent); + EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes, received); base::MessageLoop::current()->RunUntilIdle(); // Read bytes 20-29 and 50-59 from the network, bytes 30-49 from the cache. transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER; transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 "; - received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); - EXPECT_EQ(range_response_size * 2, received_bytes); + RunTransactionAndGetNetworkBytes(cache, transaction, &sent, &received); + EXPECT_EQ(MockNetworkTransaction::kTotalSentBytes * 2, sent); + EXPECT_EQ(MockNetworkTransaction::kTotalReceivedBytes * 2, received); RemoveMockTransaction(&kRangeGET_TransactionOK); } @@ -7349,6 +7461,83 @@ TEST(HttpCache, ResourceFreshnessHeaderNotSent) { EXPECT_EQ(2, cache.network_layer()->transaction_count()); } +TEST(HttpCache, StaleContentNotUsedWhenLoadFlagNotSet) { + MockHttpCache cache; + + ScopedMockTransaction stale_while_revalidate_transaction( + kSimpleGET_Transaction); + + stale_while_revalidate_transaction.response_headers = + "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" + "Age: 10801\n" + "Cache-Control: max-age=0,stale-while-revalidate=86400\n"; + + // Write to the cache. + RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + + // Send the request again and check that it is sent to the network again. + HttpResponseInfo response_info; + RunTransactionTestWithResponseInfo( + cache.http_cache(), stale_while_revalidate_transaction, &response_info); + + EXPECT_EQ(2, cache.network_layer()->transaction_count()); + EXPECT_FALSE(response_info.async_revalidation_required); +} + +TEST(HttpCache, StaleContentUsedWhenLoadFlagSetAndUsable) { + MockHttpCache cache; + + ScopedMockTransaction stale_while_revalidate_transaction( + kSimpleGET_Transaction); + stale_while_revalidate_transaction.load_flags |= + LOAD_SUPPORT_ASYNC_REVALIDATION; + stale_while_revalidate_transaction.response_headers = + "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" + "Age: 10801\n" + "Cache-Control: max-age=0,stale-while-revalidate=86400\n"; + + // Write to the cache. + RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + + // Send the request again and check that it is not sent to the network again. + HttpResponseInfo response_info; + RunTransactionTestWithResponseInfo( + cache.http_cache(), stale_while_revalidate_transaction, &response_info); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + EXPECT_TRUE(response_info.async_revalidation_required); +} + +TEST(HttpCache, StaleContentNotUsedWhenUnusable) { + MockHttpCache cache; + + ScopedMockTransaction stale_while_revalidate_transaction( + kSimpleGET_Transaction); + stale_while_revalidate_transaction.load_flags |= + LOAD_SUPPORT_ASYNC_REVALIDATION; + stale_while_revalidate_transaction.response_headers = + "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" + "Age: 10801\n" + "Cache-Control: max-age=0,stale-while-revalidate=1800\n"; + + // Write to the cache. + RunTransactionTest(cache.http_cache(), stale_while_revalidate_transaction); + + EXPECT_EQ(1, cache.network_layer()->transaction_count()); + + // Send the request again and check that it is sent to the network again. + HttpResponseInfo response_info; + RunTransactionTestWithResponseInfo( + cache.http_cache(), stale_while_revalidate_transaction, &response_info); + + EXPECT_EQ(2, cache.network_layer()->transaction_count()); + EXPECT_FALSE(response_info.async_revalidation_required); +} + // Tests that we allow multiple simultaneous, non-overlapping transactions to // take place on a sparse entry. TEST(HttpCache, RangeGET_MultipleRequests) { diff --git a/chromium/net/http/http_content_disposition.cc b/chromium/net/http/http_content_disposition.cc index 0e830f609bc..28ea8bd5547 100644 --- a/chromium/net/http/http_content_disposition.cc +++ b/chromium/net/http/http_content_disposition.cc @@ -359,9 +359,11 @@ std::string::const_iterator HttpContentDisposition::ConsumeDispositionType( DCHECK(std::find(type_begin, type_end, '=') == type_end); - if (base::LowerCaseEqualsASCII(type_begin, type_end, "inline")) { + if (base::LowerCaseEqualsASCII(base::StringPiece(type_begin, type_end), + "inline")) { type_ = INLINE; - } else if (base::LowerCaseEqualsASCII(type_begin, type_end, "attachment")) { + } else if (base::LowerCaseEqualsASCII(base::StringPiece(type_begin, type_end), + "attachment")) { type_ = ATTACHMENT; } else { parse_result_flags_ |= HAS_UNKNOWN_DISPOSITION_TYPE; @@ -403,15 +405,17 @@ void HttpContentDisposition::Parse(const std::string& header, HttpUtil::NameValuePairsIterator iter(pos, end, ';'); while (iter.GetNext()) { if (filename.empty() && - base::LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(), - "filename")) { + base::LowerCaseEqualsASCII( + base::StringPiece(iter.name_begin(), iter.name_end()), + "filename")) { DecodeFilenameValue(iter.value(), referrer_charset, &filename, &parse_result_flags_); if (!filename.empty()) parse_result_flags_ |= HAS_FILENAME; } else if (ext_filename.empty() && - base::LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(), - "filename*")) { + base::LowerCaseEqualsASCII( + base::StringPiece(iter.name_begin(), iter.name_end()), + "filename*")) { DecodeExtValue(iter.raw_value(), &ext_filename); if (!ext_filename.empty()) parse_result_flags_ |= HAS_EXT_FILENAME; diff --git a/chromium/net/http/http_log_util.cc b/chromium/net/http/http_log_util.cc index 0467fb605ab..87c2fd99f19 100644 --- a/chromium/net/http/http_log_util.cc +++ b/chromium/net/http/http_log_util.cc @@ -19,7 +19,7 @@ bool ShouldRedactChallenge(HttpAuthChallengeTokenizer* challenge) { if (challenge->challenge_text().find(',') != std::string::npos) return false; - std::string scheme = base::StringToLowerASCII(challenge->scheme()); + std::string scheme = base::ToLowerASCII(challenge->scheme()); // Invalid input. if (scheme.empty()) return false; @@ -45,15 +45,15 @@ std::string ElideHeaderValueForNetLog(NetLogCaptureMode capture_mode, // Note: this logic should be kept in sync with stripCookiesAndLoginInfo in // chrome/browser/resources/net_internals/log_view_painter.js. - if (!base::strcasecmp(header.c_str(), "set-cookie") || - !base::strcasecmp(header.c_str(), "set-cookie2") || - !base::strcasecmp(header.c_str(), "cookie") || - !base::strcasecmp(header.c_str(), "authorization") || - !base::strcasecmp(header.c_str(), "proxy-authorization")) { + if (base::EqualsCaseInsensitiveASCII(header, "set-cookie") || + base::EqualsCaseInsensitiveASCII(header, "set-cookie2") || + base::EqualsCaseInsensitiveASCII(header, "cookie") || + base::EqualsCaseInsensitiveASCII(header, "authorization") || + base::EqualsCaseInsensitiveASCII(header, "proxy-authorization")) { redact_begin = value.begin(); redact_end = value.end(); - } else if (!base::strcasecmp(header.c_str(), "www-authenticate") || - !base::strcasecmp(header.c_str(), "proxy-authenticate")) { + } else if (base::EqualsCaseInsensitiveASCII(header, "www-authenticate") || + base::EqualsCaseInsensitiveASCII(header, "proxy-authenticate")) { // Look for authentication information from data received from the server // in multi-round Negotiate authentication. HttpAuthChallengeTokenizer challenge(value.begin(), value.end()); diff --git a/chromium/net/http/http_network_layer.cc b/chromium/net/http/http_network_layer.cc index e0b3199bb89..8e6b35cb25e 100644 --- a/chromium/net/http/http_network_layer.cc +++ b/chromium/net/http/http_network_layer.cc @@ -38,14 +38,6 @@ HttpNetworkLayer::~HttpNetworkLayer() { #endif } -// static -HttpTransactionFactory* HttpNetworkLayer::CreateFactory( - HttpNetworkSession* session) { - DCHECK(session); - - return new HttpNetworkLayer(session); -} - int HttpNetworkLayer::CreateTransaction(RequestPriority priority, scoped_ptr<HttpTransaction>* trans) { if (suspended_) diff --git a/chromium/net/http/http_network_layer.h b/chromium/net/http/http_network_layer.h index 23b4e1eb2db..5ade926c3bd 100644 --- a/chromium/net/http/http_network_layer.h +++ b/chromium/net/http/http_network_layer.h @@ -30,14 +30,6 @@ class NET_EXPORT HttpNetworkLayer explicit HttpNetworkLayer(HttpNetworkSession* session); ~HttpNetworkLayer() override; - // Create a transaction factory that instantiate a network layer over an - // existing network session. Network session contains some valuable - // information (e.g. authentication data) that we want to share across - // multiple network layers. This method exposes the implementation details - // of a network layer, use this method with an existing network layer only - // when network session is shared. - static HttpTransactionFactory* CreateFactory(HttpNetworkSession* session); - // HttpTransactionFactory methods: int CreateTransaction(RequestPriority priority, scoped_ptr<HttpTransaction>* trans) override; diff --git a/chromium/net/http/http_network_layer_unittest.cc b/chromium/net/http/http_network_layer_unittest.cc index 9128cdd3da8..153423e45ff 100644 --- a/chromium/net/http/http_network_layer_unittest.cc +++ b/chromium/net/http/http_network_layer_unittest.cc @@ -32,10 +32,10 @@ class HttpNetworkLayerTest : public PlatformTest { ConfigureTestDependencies(ProxyService::CreateDirect()); } - void ConfigureTestDependencies(ProxyService* proxy_service) { + void ConfigureTestDependencies(scoped_ptr<ProxyService> proxy_service) { cert_verifier_.reset(new MockCertVerifier); transport_security_state_.reset(new TransportSecurityState); - proxy_service_.reset(proxy_service); + proxy_service_ = proxy_service.Pass(); HttpNetworkSession::Params session_params; session_params.client_socket_factory = &mock_socket_factory_; session_params.host_resolver = &host_resolver_; diff --git a/chromium/net/http/http_network_session.cc b/chromium/net/http/http_network_session.cc index 950a0281bda..4c0009cd15f 100644 --- a/chromium/net/http/http_network_session.cc +++ b/chromium/net/http/http_network_session.cc @@ -79,6 +79,7 @@ HttpNetworkSession::Params::Params() network_delegate(NULL), net_log(NULL), host_mapping_rules(NULL), + socket_performance_watcher_factory(NULL), ignore_certificate_errors(false), testing_fixed_http_port(0), testing_fixed_https_port(0), @@ -90,10 +91,10 @@ HttpNetworkSession::Params::Params() spdy_stream_max_recv_window_size(kSpdyStreamMaxRecvWindowSize), spdy_initial_max_concurrent_streams(0), time_func(&base::TimeTicks::Now), - use_alternate_protocols(false), + use_alternative_services(false), alternative_service_probability_threshold(1), enable_quic(false), - disable_insecure_quic(false), + enable_insecure_quic(false), enable_quic_for_proxies(false), enable_quic_port_selection(true), quic_always_require_handshake_confirmation(false), @@ -103,9 +104,10 @@ HttpNetworkSession::Params::Params() quic_enable_non_blocking_io(false), quic_disable_disk_cache(false), quic_prefer_aes(false), - quic_max_number_of_lossy_connections(0), - quic_packet_loss_threshold(1.0f), + quic_max_number_of_lossy_connections(4), + quic_packet_loss_threshold(0.5f), quic_socket_receive_buffer_size(kQuicSocketReceiveBufferSize), + quic_delay_tcp_race(false), quic_clock(NULL), quic_random(NULL), quic_max_packet_length(kDefaultMaxPacketSize), @@ -140,8 +142,10 @@ HttpNetworkSession::HttpNetworkSession(const Params& params) : ClientSocketFactory::GetDefaultFactory(), params.http_server_properties, params.cert_verifier, + params.cert_policy_enforcer, params.channel_id_service, params.transport_security_state, + params.socket_performance_watcher_factory, params.quic_crypto_client_stream_factory, params.quic_random ? params.quic_random : QuicRandom::GetInstance(), params.quic_clock ? params.quic_clock : new QuicClock(), @@ -162,6 +166,7 @@ HttpNetworkSession::HttpNetworkSession(const Params& params) params.quic_threshold_public_resets_post_handshake, params.quic_threshold_timeouts_streams_open, params.quic_socket_receive_buffer_size, + params.quic_delay_tcp_race, params.quic_connection_options), spdy_session_pool_(params.host_resolver, params.ssl_config_service, diff --git a/chromium/net/http/http_network_session.h b/chromium/net/http/http_network_session.h index d67182b1cef..c0503c9f73c 100644 --- a/chromium/net/http/http_network_session.h +++ b/chromium/net/http/http_network_session.h @@ -48,6 +48,7 @@ class ProxyService; class QuicClock; class QuicCryptoClientStreamFactory; class QuicServerInfoFactory; +class SocketPerformanceWatcherFactory; class SOCKSClientSocketPool; class SSLClientSocketPool; class SSLConfigService; @@ -78,6 +79,7 @@ class NET_EXPORT HttpNetworkSession base::WeakPtr<HttpServerProperties> http_server_properties; NetLog* net_log; HostMappingRules* host_mapping_rules; + SocketPerformanceWatcherFactory* socket_performance_watcher_factory; bool ignore_certificate_errors; uint16 testing_fixed_http_port; uint16 testing_fixed_https_port; @@ -99,13 +101,11 @@ class NET_EXPORT HttpNetworkSession std::string trusted_spdy_proxy; // URLs to exclude from forced SPDY. std::set<HostPortPair> forced_spdy_exclusions; - // Noe: Using this in the case of NPN for HTTP only results in the browser - // trying SSL and then falling back to http. - bool use_alternate_protocols; + bool use_alternative_services; double alternative_service_probability_threshold; bool enable_quic; - bool disable_insecure_quic; + bool enable_insecure_quic; bool enable_quic_for_proxies; bool enable_quic_port_selection; bool quic_always_require_handshake_confirmation; @@ -118,6 +118,7 @@ class NET_EXPORT HttpNetworkSession int quic_max_number_of_lossy_connections; float quic_packet_loss_threshold; int quic_socket_receive_buffer_size; + bool quic_delay_tcp_race; HostPortPair origin_to_force_quic_on; QuicClock* quic_clock; // Will be owned by QuicStreamFactory. QuicRandom* quic_random; diff --git a/chromium/net/http/http_network_transaction.cc b/chromium/net/http/http_network_transaction.cc index 76e352eed92..c12f95dfa67 100644 --- a/chromium/net/http/http_network_transaction.cc +++ b/chromium/net/http/http_network_transaction.cc @@ -67,10 +67,21 @@ namespace net { namespace { -void ProcessAlternateProtocol( - HttpNetworkSession* session, - const HttpResponseHeaders& headers, - const HostPortPair& http_host_port_pair) { +void ProcessAlternativeServices(HttpNetworkSession* session, + const HttpResponseHeaders& headers, + const HostPortPair& http_host_port_pair) { + if (session->params().use_alternative_services && + headers.HasHeader(kAlternativeServiceHeader)) { + std::string alternative_service_str; + headers.GetNormalizedHeader(kAlternativeServiceHeader, + &alternative_service_str); + session->http_stream_factory()->ProcessAlternativeService( + session->http_server_properties(), alternative_service_str, + http_host_port_pair, *session); + // If there is an "Alt-Svc" header, then ignore "Alternate-Protocol". + return; + } + if (!headers.HasHeader(kAlternateProtocolHeader)) return; @@ -138,6 +149,7 @@ HttpNetworkTransaction::HttpNetworkTransaction(RequestPriority priority, request_headers_(), read_buf_len_(0), total_received_bytes_(0), + total_sent_bytes_(0), next_state_(STATE_NONE), establishing_tunnel_(false), websocket_handshake_stream_base_create_helper_(NULL) { @@ -148,28 +160,18 @@ HttpNetworkTransaction::HttpNetworkTransaction(RequestPriority priority, HttpNetworkTransaction::~HttpNetworkTransaction() { if (stream_.get()) { - HttpResponseHeaders* headers = GetResponseHeaders(); // TODO(mbelshe): The stream_ should be able to compute whether or not the // stream should be kept alive. No reason to compute here // and pass it in. - bool try_to_keep_alive = - next_state_ == STATE_NONE && - stream_->CanFindEndOfResponse() && - (!headers || headers->IsKeepAlive()); - if (!try_to_keep_alive) { + if (!stream_->CanReuseConnection() || next_state_ != STATE_NONE) { stream_->Close(true /* not reusable */); + } else if (stream_->IsResponseBodyComplete()) { + // If the response body is complete, we can just reuse the socket. + stream_->Close(false /* reusable */); } else { - if (stream_->IsResponseBodyComplete()) { - // If the response body is complete, we can just reuse the socket. - stream_->Close(false /* reusable */); - } else if (stream_->IsSpdyHttpStream()) { - // Doesn't really matter for SpdyHttpStream. Just close it. - stream_->Close(true /* not reusable */); - } else { - // Otherwise, we try to drain the response body. - HttpStream* stream = stream_.release(); - stream->Drain(session_); - } + // Otherwise, we try to drain the response body. + HttpStream* stream = stream_.release(); + stream->Drain(session_); } } @@ -195,12 +197,6 @@ int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info, if (request_->privacy_mode == PRIVACY_MODE_ENABLED) server_ssl_config_.channel_id_enabled = false; - if (server_ssl_config_.fastradio_padding_enabled) { - server_ssl_config_.fastradio_padding_eligible = - session_->ssl_config_service()->SupportsFastradioPadding( - request_info->url); - } - next_state_ = STATE_NOTIFY_BEFORE_CREATE_STREAM; int rv = DoLoop(OK); if (rv == ERR_IO_PENDING) @@ -288,8 +284,7 @@ void HttpNetworkTransaction::PrepareForAuthRestart(HttpAuth::Target target) { bool keep_alive = false; // Even if the server says the connection is keep-alive, we have to be // able to find the end of each response in order to reuse the connection. - if (GetResponseHeaders()->IsKeepAlive() && - stream_->CanFindEndOfResponse()) { + if (stream_->CanReuseConnection()) { // If the response body hasn't been completely read, we need to drain // it first. if (!stream_->IsResponseBodyComplete()) { @@ -311,8 +306,9 @@ void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) { if (stream_.get()) { total_received_bytes_ += stream_->GetTotalReceivedBytes(); + total_sent_bytes_ += stream_->GetTotalSentBytes(); HttpStream* new_stream = NULL; - if (keep_alive && stream_->IsConnectionReusable()) { + if (keep_alive && stream_->CanReuseConnection()) { // We should call connection_->set_idle_time(), but this doesn't occur // often enough to be worth the trouble. stream_->SetConnectionReused(); @@ -326,8 +322,9 @@ void HttpNetworkTransaction::DidDrainBodyForAuthRestart(bool keep_alive) { stream_->Close(true); next_state_ = STATE_CREATE_STREAM; } else { - // Renewed streams shouldn't carry over received bytes. + // Renewed streams shouldn't carry over sent or received bytes. DCHECK_EQ(0, new_stream->GetTotalReceivedBytes()); + DCHECK_EQ(0, new_stream->GetTotalSentBytes()); next_state_ = STATE_INIT_STREAM; } stream_.reset(new_stream); @@ -390,13 +387,20 @@ bool HttpNetworkTransaction::GetFullRequestHeaders( return true; } -int64 HttpNetworkTransaction::GetTotalReceivedBytes() const { - int64 total_received_bytes = total_received_bytes_; +int64_t HttpNetworkTransaction::GetTotalReceivedBytes() const { + int64_t total_received_bytes = total_received_bytes_; if (stream_) total_received_bytes += stream_->GetTotalReceivedBytes(); return total_received_bytes; } +int64_t HttpNetworkTransaction::GetTotalSentBytes() const { + int64_t total_sent_bytes = total_sent_bytes_; + if (stream_) + total_sent_bytes += stream_->GetTotalSentBytes(); + return total_sent_bytes; +} + void HttpNetworkTransaction::DoneReading() {} const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const { @@ -447,6 +451,14 @@ bool HttpNetworkTransaction::GetLoadTimingInfo( return true; } +bool HttpNetworkTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const { + if (!remote_endpoint_.address().size()) + return false; + + *endpoint = remote_endpoint_; + return true; +} + void HttpNetworkTransaction::SetPriority(RequestPriority priority) { priority_ = priority; if (stream_request_) @@ -481,8 +493,10 @@ void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config, DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_); DCHECK(stream_request_.get()); - if (stream_) + if (stream_) { total_received_bytes_ += stream_->GetTotalReceivedBytes(); + total_sent_bytes_ += stream_->GetTotalSentBytes(); + } stream_.reset(stream); server_ssl_config_ = used_ssl_config; proxy_info_ = used_proxy_info; @@ -581,8 +595,10 @@ void HttpNetworkTransaction::OnHttpsProxyTunnelResponse( response_ = response_info; server_ssl_config_ = used_ssl_config; proxy_info_ = used_proxy_info; - if (stream_) + if (stream_) { total_received_bytes_ += stream_->GetTotalReceivedBytes(); + total_sent_bytes_ += stream_->GetTotalSentBytes(); + } stream_.reset(stream); stream_request_.reset(); // we're done with the stream request OnIOComplete(ERR_HTTPS_PROXY_TUNNEL_RESPONSE); @@ -805,6 +821,9 @@ int HttpNetworkTransaction::DoCreateStreamComplete(int result) { int HttpNetworkTransaction::DoInitStream() { DCHECK(stream_.get()); next_state_ = STATE_INIT_STREAM_COMPLETE; + + stream_->GetRemoteEndpoint(&remote_endpoint_); + return stream_->InitializeStream(request_, priority_, net_log_, io_callback_); } @@ -816,8 +835,10 @@ int HttpNetworkTransaction::DoInitStreamComplete(int result) { result = HandleIOError(result); // The stream initialization failed, so this stream will never be useful. - if (stream_) - total_received_bytes_ += stream_->GetTotalReceivedBytes(); + if (stream_) { + total_received_bytes_ += stream_->GetTotalReceivedBytes(); + total_sent_bytes_ += stream_->GetTotalSentBytes(); + } stream_.reset(); } @@ -896,12 +917,13 @@ void HttpNetworkTransaction::BuildRequestHeaders( HttpRequestHeaders::kContentLength, base::Uint64ToString(request_->upload_data_stream->size())); } - } else if (request_->method == "POST" || request_->method == "PUT" || - request_->method == "HEAD") { + } else if (request_->method == "POST" || request_->method == "PUT") { // An empty POST/PUT request still needs a content length. As for HEAD, // IE and Safari also add a content length header. Presumably it is to // support sending a HEAD request to an URL that only expects to be sent a // POST or some other method that normally would have a message body. + // Firefox (40.0) does not send the header, and RFC 7230 & 7231 + // specify that it should not be sent due to undefined behavior. request_headers_.SetHeader(HttpRequestHeaders::kContentLength, "0"); } @@ -1077,8 +1099,8 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) { return OK; } - ProcessAlternateProtocol(session_, *response_.headers.get(), - HostPortPair::FromURL(request_->url)); + ProcessAlternativeServices(session_, *response_.headers.get(), + HostPortPair::FromURL(request_->url)); int rv = HandleAuthChallenge(); if (rv != OK) @@ -1109,26 +1131,18 @@ int HttpNetworkTransaction::DoReadBodyComplete(int result) { done = true; } - bool keep_alive = false; - if (stream_->IsResponseBodyComplete()) { + // Clean up connection if we are done. + if (done) { // Note: Just because IsResponseBodyComplete is true, we're not // necessarily "done". We're only "done" when it is the last // read on this HttpNetworkTransaction, which will be signified // by a zero-length read. - // TODO(mbelshe): The keepalive property is really a property of + // TODO(mbelshe): The keep-alive property is really a property of // the stream. No need to compute it here just to pass back // to the stream's Close function. - // TODO(rtenneti): CanFindEndOfResponse should return false if there are no - // ResponseHeaders. - if (stream_->CanFindEndOfResponse()) { - HttpResponseHeaders* headers = GetResponseHeaders(); - if (headers) - keep_alive = headers->IsKeepAlive(); - } - } + bool keep_alive = + stream_->IsResponseBodyComplete() && stream_->CanReuseConnection(); - // Clean up connection if we are done. - if (done) { stream_->Close(!keep_alive); // Note: we don't reset the stream here. We've closed it, but we still // need it around so that callers can call methods such as @@ -1198,6 +1212,7 @@ int HttpNetworkTransaction::HandleCertificateRequest(int error) { // renegotiation. DCHECK(!stream_request_.get()); total_received_bytes_ += stream_->GetTotalReceivedBytes(); + total_sent_bytes_ += stream_->GetTotalSentBytes(); stream_->Close(true); stream_.reset(); } @@ -1421,8 +1436,10 @@ int HttpNetworkTransaction::HandleIOError(int error) { void HttpNetworkTransaction::ResetStateForRestart() { ResetStateForAuthRestart(); - if (stream_) + if (stream_) { total_received_bytes_ += stream_->GetTotalReceivedBytes(); + total_sent_bytes_ += stream_->GetTotalSentBytes(); + } stream_.reset(); } @@ -1437,6 +1454,7 @@ void HttpNetworkTransaction::ResetStateForAuthRestart() { request_headers_.Clear(); response_ = HttpResponseInfo(); establishing_tunnel_ = false; + remote_endpoint_ = IPEndPoint(); } void HttpNetworkTransaction::RecordSSLFallbackMetrics(int result) { @@ -1444,7 +1462,8 @@ void HttpNetworkTransaction::RecordSSLFallbackMetrics(int result) { return; const std::string& host = request_->url.host(); - bool is_google = base::EndsWith(host, "google.com", true) && + bool is_google = base::EndsWith(host, "google.com", + base::CompareCase::SENSITIVE) && (host.size() == 10 || host[host.size() - 11] == '.'); if (is_google) { // Some fraction of successful connections use the fallback, but only due to diff --git a/chromium/net/http/http_network_transaction.h b/chromium/net/http/http_network_transaction.h index ed4597d94fa..a5e5b080323 100644 --- a/chromium/net/http/http_network_transaction.h +++ b/chromium/net/http/http_network_transaction.h @@ -5,6 +5,8 @@ #ifndef NET_HTTP_HTTP_NETWORK_TRANSACTION_H_ #define NET_HTTP_HTTP_NETWORK_TRANSACTION_H_ +#include <stdint.h> + #include <string> #include "base/basictypes.h" @@ -62,13 +64,15 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction const CompletionCallback& callback) override; void StopCaching() override; bool GetFullRequestHeaders(HttpRequestHeaders* headers) const override; - int64 GetTotalReceivedBytes() const override; + int64_t GetTotalReceivedBytes() const override; + int64_t GetTotalSentBytes() const override; void DoneReading() override; const HttpResponseInfo* GetResponseInfo() const override; LoadState GetLoadState() const override; UploadProgress GetUploadProgress() const override; void SetQuicServerInfo(QuicServerInfo* quic_server_info) override; bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; + bool GetRemoteEndpoint(IPEndPoint* endpoint) const override; void SetPriority(RequestPriority priority) override; void SetWebSocketHandshakeStreamCreateHelper( WebSocketHandshakeStreamBase::CreateHelper* create_helper) override; @@ -319,8 +323,13 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction scoped_refptr<IOBuffer> read_buf_; int read_buf_len_; - // Total number of bytes received on streams for this transaction. - int64 total_received_bytes_; + // Total number of bytes received on all destroyed HttpStreams for this + // transaction. + int64_t total_received_bytes_; + + // Total number of bytes sent on all destroyed HttpStreams for this + // transaction. + int64_t total_sent_bytes_; // When the transaction started / finished sending the request, including // the body, if present. @@ -343,6 +352,7 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction BeforeProxyHeadersSentCallback before_proxy_headers_sent_callback_; ConnectionAttempts connection_attempts_; + IPEndPoint remote_endpoint_; DISALLOW_COPY_AND_ASSIGN(HttpNetworkTransaction); }; diff --git a/chromium/net/http/http_network_transaction_ssl_unittest.cc b/chromium/net/http/http_network_transaction_ssl_unittest.cc index 2db5a9997c9..da28d9cd74d 100644 --- a/chromium/net/http/http_network_transaction_ssl_unittest.cc +++ b/chromium/net/http/http_network_transaction_ssl_unittest.cc @@ -65,7 +65,7 @@ class HttpNetworkTransactionSSLTest : public testing::Test { auth_handler_factory_.reset(new HttpAuthHandlerMock::Factory()); session_params_.http_auth_handler_factory = auth_handler_factory_.get(); - proxy_service_.reset(ProxyService::CreateDirect()); + proxy_service_ = ProxyService::CreateDirect(); session_params_.proxy_service = proxy_service_.get(); session_params_.client_socket_factory = &mock_socket_factory_; diff --git a/chromium/net/http/http_network_transaction_unittest.cc b/chromium/net/http/http_network_transaction_unittest.cc index 1813c809ea5..fb65846782a 100644 --- a/chromium/net/http/http_network_transaction_unittest.cc +++ b/chromium/net/http/http_network_transaction_unittest.cc @@ -6,6 +6,8 @@ #include <math.h> // ceil #include <stdarg.h> +#include <stdint.h> + #include <string> #include <vector> @@ -263,9 +265,11 @@ class HttpNetworkTransactionTest int rv; std::string status_line; std::string response_data; - int64 totalReceivedBytes; + int64_t total_received_bytes; + int64_t total_sent_bytes; LoadTimingInfo load_timing_info; ConnectionAttempts connection_attempts; + IPEndPoint remote_endpoint_after_start; }; void SetUp() override { @@ -288,10 +292,14 @@ class HttpNetworkTransactionTest AlternateProtocolToString(AlternateProtocolFromNextProto(GetParam())); } - // This is the expected return from a current server advertising SPDY. + std::string GetAlternativeServiceHttpHeader() { + return std::string("Alt-Svc: ") + GetAlternateProtocolFromParam() + + "=\"www.example.com:443\"\r\n"; + } + std::string GetAlternateProtocolHttpHeader() { return std::string("Alternate-Protocol: 443:") + - GetAlternateProtocolFromParam() + "\r\n\r\n"; + GetAlternateProtocolFromParam() + "\r\n"; } // Either |write_failure| specifies a write failure or |read_failure| @@ -335,6 +343,8 @@ class HttpNetworkTransactionTest EXPECT_EQ(ERR_IO_PENDING, rv); out.rv = callback.WaitForResult(); + out.total_received_bytes = trans->GetTotalReceivedBytes(); + out.total_sent_bytes = trans->GetTotalSentBytes(); // Even in the failure cases that use this function, connections are always // successfully established before the error. @@ -356,6 +366,11 @@ class HttpNetworkTransactionTest EXPECT_EQ("127.0.0.1", response->socket_address.host()); EXPECT_EQ(80, response->socket_address.port()); + bool got_endpoint = + trans->GetRemoteEndpoint(&out.remote_endpoint_after_start); + EXPECT_EQ(got_endpoint, + out.remote_endpoint_after_start.address().size() > 0); + rv = ReadTransaction(trans.get(), &out.response_data); EXPECT_EQ(OK, rv); @@ -386,23 +401,30 @@ class HttpNetworkTransactionTest EXPECT_EQ("['Host: www.example.org','Connection: keep-alive']", response_headers); - out.totalReceivedBytes = trans->GetTotalReceivedBytes(); + out.total_received_bytes = trans->GetTotalReceivedBytes(); + // The total number of sent bytes should not have changed. + EXPECT_EQ(out.total_sent_bytes, trans->GetTotalSentBytes()); + trans->GetConnectionAttempts(&out.connection_attempts); return out; } SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[], size_t reads_count) { - StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0); - StaticSocketDataProvider* data[] = { &reads }; - return SimpleGetHelperForData(data, 1); - } + MockWrite data_writes[] = { + MockWrite("GET / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n\r\n"), + }; - int64 ReadsSize(MockRead data_reads[], size_t reads_count) { - int64 size = 0; - for (size_t i = 0; i < reads_count; ++i) - size += data_reads[i].data_len; - return size; + StaticSocketDataProvider reads(data_reads, reads_count, data_writes, + arraysize(data_writes)); + StaticSocketDataProvider* data[] = {&reads}; + SimpleGetHelperResult out = SimpleGetHelperForData(data, 1); + + EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)), + out.total_sent_bytes); + return out; } void ConnectStatusHelperWithExpectedStatus(const MockRead& status, @@ -426,7 +448,6 @@ class HttpNetworkTransactionTest INSTANTIATE_TEST_CASE_P(NextProto, HttpNetworkTransactionTest, testing::Values(kProtoSPDY31, - kProtoHTTP2_14, kProtoHTTP2)); namespace { @@ -494,6 +515,7 @@ void FillLargeHeadersString(std::string* str, int size) { str->append(row, sizeof_row); } +#if defined(NTLM_PORTABLE) // Alternative functions that eliminate randomness and dependency on the local // host name so that the generated NTLM messages are reproducible. void MockGenerateRandom1(uint8* output, size_t n) { @@ -522,6 +544,7 @@ void MockGenerateRandom2(uint8* output, size_t n) { std::string MockGetHostName() { return "WTC-WIN7"; } +#endif // defined(NTLM_PORTABLE) template<typename ParentPool> class CaptureGroupNameSocketPool : public ParentPool { @@ -641,6 +664,7 @@ bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) { return true; } +#if defined(NTLM_PORTABLE) bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) { if (!auth_challenge) return false; @@ -650,6 +674,7 @@ bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) { EXPECT_EQ("ntlm", auth_challenge->scheme); return true; } +#endif // defined(NTLM_PORTABLE) } // namespace @@ -670,9 +695,11 @@ TEST_P(HttpNetworkTransactionTest, SimpleGET) { EXPECT_EQ(OK, out.rv); EXPECT_EQ("HTTP/1.0 200 OK", out.status_line); EXPECT_EQ("hello world", out.response_data); - int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); - EXPECT_EQ(reads_size, out.totalReceivedBytes); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); + EXPECT_EQ(reads_size, out.total_received_bytes); EXPECT_EQ(0u, out.connection_attempts.size()); + + EXPECT_FALSE(out.remote_endpoint_after_start.address().empty()); } // Response with no status line. @@ -686,8 +713,8 @@ TEST_P(HttpNetworkTransactionTest, SimpleGETNoHeaders) { EXPECT_EQ(OK, out.rv); EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); EXPECT_EQ("hello world", out.response_data); - int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); - EXPECT_EQ(reads_size, out.totalReceivedBytes); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); + EXPECT_EQ(reads_size, out.total_received_bytes); } // Allow up to 4 bytes of junk to precede status line. @@ -701,8 +728,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk3Bytes) { EXPECT_EQ(OK, out.rv); EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); EXPECT_EQ("DATA", out.response_data); - int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); - EXPECT_EQ(reads_size, out.totalReceivedBytes); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); + EXPECT_EQ(reads_size, out.total_received_bytes); } // Allow up to 4 bytes of junk to precede status line. @@ -716,8 +743,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes) { EXPECT_EQ(OK, out.rv); EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); EXPECT_EQ("DATA", out.response_data); - int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); - EXPECT_EQ(reads_size, out.totalReceivedBytes); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); + EXPECT_EQ(reads_size, out.total_received_bytes); } // Beyond 4 bytes of slop and it should fail to find a status line. @@ -731,8 +758,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk5Bytes) { EXPECT_EQ(OK, out.rv); EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data); - int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); - EXPECT_EQ(reads_size, out.totalReceivedBytes); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); + EXPECT_EQ(reads_size, out.total_received_bytes); } // Same as StatusLineJunk4Bytes, except the read chunks are smaller. @@ -750,8 +777,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) { EXPECT_EQ(OK, out.rv); EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line); EXPECT_EQ("DATA", out.response_data); - int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); - EXPECT_EQ(reads_size, out.totalReceivedBytes); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); + EXPECT_EQ(reads_size, out.total_received_bytes); } // Close the connection before enough bytes to have a status line. @@ -765,8 +792,8 @@ TEST_P(HttpNetworkTransactionTest, StatusLinePartial) { EXPECT_EQ(OK, out.rv); EXPECT_EQ("HTTP/0.9 200 OK", out.status_line); EXPECT_EQ("HTT", out.response_data); - int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); - EXPECT_EQ(reads_size, out.totalReceivedBytes); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); + EXPECT_EQ(reads_size, out.total_received_bytes); } // Simulate a 204 response, lacking a Content-Length header, sent over a @@ -784,9 +811,9 @@ TEST_P(HttpNetworkTransactionTest, StopsReading204) { EXPECT_EQ(OK, out.rv); EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line); EXPECT_EQ("", out.response_data); - int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); - int64 response_size = reads_size - strlen(junk); - EXPECT_EQ(response_size, out.totalReceivedBytes); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); + int64_t response_size = reads_size - strlen(junk); + EXPECT_EQ(response_size, out.total_received_bytes); } // A simple request using chunked encoding with some extra data after. @@ -808,9 +835,9 @@ TEST_P(HttpNetworkTransactionTest, ChunkedEncoding) { EXPECT_EQ(OK, out.rv); EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); EXPECT_EQ("Hello world", out.response_data); - int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); - int64 response_size = reads_size - extra_data.size(); - EXPECT_EQ(response_size, out.totalReceivedBytes); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); + int64_t response_size = reads_size - extra_data.size(); + EXPECT_EQ(response_size, out.total_received_bytes); } // Next tests deal with http://crbug.com/56344. @@ -1027,11 +1054,9 @@ TEST_P(HttpNetworkTransactionTest, Head) { base::Unretained(&proxy_headers_handler))); MockWrite data_writes1[] = { - MockWrite( - "HEAD / HTTP/1.1\r\n" - "Host: www.example.org\r\n" - "Connection: keep-alive\r\n" - "Content-Length: 0\r\n\r\n"), + MockWrite("HEAD / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n\r\n"), }; MockRead data_reads1[] = { MockRead("HTTP/1.1 404 Not Found\r\n"), @@ -1441,8 +1466,8 @@ void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest( SSLConfig ssl_config; session->ssl_config_service()->GetSSLConfig(&ssl_config); session->GetNextProtos(&ssl_config.next_protos); - session->http_stream_factory()->PreconnectStreams( - 1, request, DEFAULT_PRIORITY, ssl_config, ssl_config); + session->http_stream_factory()->PreconnectStreams(1, request, ssl_config, + ssl_config); // Wait for the preconnect to complete. // TODO(davidben): Some way to wait for an idle socket count might be handy. base::RunLoop().RunUntilIdle(); @@ -1585,6 +1610,10 @@ TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) { rv = callback.WaitForResult(); EXPECT_EQ(ERR_CONNECTION_RESET, rv); + + IPEndPoint endpoint; + EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint)); + EXPECT_LT(0u, endpoint.address().size()); } // What do various browsers do when the server closes a non-keepalive @@ -1948,7 +1977,9 @@ TEST_P(HttpNetworkTransactionTest, BasicAuth) { EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1)); TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES); - int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1)); + int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1)); + EXPECT_EQ(writes_size1, trans->GetTotalSentBytes()); + int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1)); EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes()); const HttpResponseInfo* response = trans->GetResponseInfo(); @@ -1973,7 +2004,9 @@ TEST_P(HttpNetworkTransactionTest, BasicAuth) { load_timing_info2.connect_timing.connect_start); EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); - int64 reads_size2 = ReadsSize(data_reads2, arraysize(data_reads2)); + int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2)); + EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes()); + int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2)); EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes()); response = trans->GetResponseInfo(); @@ -1982,6 +2015,122 @@ TEST_P(HttpNetworkTransactionTest, BasicAuth) { EXPECT_EQ(100, response->headers->GetContentLength()); } +// Test the request-challenge-retry sequence for basic auth. +// (basic auth is the easiest to mock, because it has no randomness). +TEST_P(HttpNetworkTransactionTest, BasicAuthWithAddressChange) { + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.example.org/"); + request.load_flags = 0; + + TestNetLog log; + MockHostResolver* resolver = new MockHostResolver(); + session_deps_.net_log = &log; + session_deps_.host_resolver.reset(resolver); + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + + resolver->rules()->ClearRules(); + resolver->rules()->AddRule("www.example.org", "127.0.0.1"); + + MockWrite data_writes1[] = { + MockWrite("GET / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n\r\n"), + }; + + MockRead data_reads1[] = { + MockRead("HTTP/1.0 401 Unauthorized\r\n"), + // Give a couple authenticate options (only the middle one is actually + // supported). + MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed. + MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"), + MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"), + MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), + // Large content-length -- won't matter, as connection will be reset. + MockRead("Content-Length: 10000\r\n\r\n"), + MockRead(SYNCHRONOUS, ERR_FAILED), + }; + + // After calling trans->RestartWithAuth(), this is the request we should + // be issuing -- the final header line contains the credentials. + MockWrite data_writes2[] = { + MockWrite("GET / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n" + "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), + }; + + // Lastly, the server responds with the actual content. + MockRead data_reads2[] = { + MockRead("HTTP/1.0 200 OK\r\n"), + MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"), + MockRead("Content-Length: 100\r\n\r\n"), MockRead(SYNCHRONOUS, OK), + }; + + StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), + data_writes1, arraysize(data_writes1)); + StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), + data_writes2, arraysize(data_writes2)); + session_deps_.socket_factory->AddSocketDataProvider(&data1); + session_deps_.socket_factory->AddSocketDataProvider(&data2); + + TestCompletionCallback callback1; + + EXPECT_EQ(OK, callback1.GetResult(trans->Start(&request, callback1.callback(), + BoundNetLog()))); + + LoadTimingInfo load_timing_info1; + EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info1)); + TestLoadTimingNotReused(load_timing_info1, CONNECT_TIMING_HAS_DNS_TIMES); + + int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1)); + EXPECT_EQ(writes_size1, trans->GetTotalSentBytes()); + int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1)); + EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes()); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response); + EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get())); + + IPEndPoint endpoint; + EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint)); + ASSERT_FALSE(endpoint.address().empty()); + EXPECT_EQ("127.0.0.1:80", endpoint.ToString()); + + resolver->rules()->ClearRules(); + resolver->rules()->AddRule("www.example.org", "127.0.0.2"); + + TestCompletionCallback callback2; + + EXPECT_EQ(OK, callback2.GetResult(trans->RestartWithAuth( + AuthCredentials(kFoo, kBar), callback2.callback()))); + + LoadTimingInfo load_timing_info2; + EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info2)); + TestLoadTimingNotReused(load_timing_info2, CONNECT_TIMING_HAS_DNS_TIMES); + // The load timing after restart should have a new socket ID, and times after + // those of the first load timing. + EXPECT_LE(load_timing_info1.receive_headers_end, + load_timing_info2.connect_timing.connect_start); + EXPECT_NE(load_timing_info1.socket_log_id, load_timing_info2.socket_log_id); + + int64_t writes_size2 = CountWriteBytes(data_writes2, arraysize(data_writes2)); + EXPECT_EQ(writes_size1 + writes_size2, trans->GetTotalSentBytes()); + int64_t reads_size2 = CountReadBytes(data_reads2, arraysize(data_reads2)); + EXPECT_EQ(reads_size1 + reads_size2, trans->GetTotalReceivedBytes()); + + response = trans->GetResponseInfo(); + ASSERT_TRUE(response); + EXPECT_FALSE(response->auth_challenge.get()); + EXPECT_EQ(100, response->headers->GetContentLength()); + + EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint)); + ASSERT_FALSE(endpoint.address().empty()); + EXPECT_EQ("127.0.0.2:80", endpoint.ToString()); +} + TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) { HttpRequestInfo request; request.method = "GET"; @@ -2019,7 +2168,9 @@ TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) { rv = callback.WaitForResult(); EXPECT_EQ(0, rv); - int64 reads_size = ReadsSize(data_reads, arraysize(data_reads)); + int64_t writes_size = CountWriteBytes(data_writes, arraysize(data_writes)); + EXPECT_EQ(writes_size, trans->GetTotalSentBytes()); + int64_t reads_size = CountReadBytes(data_reads, arraysize(data_reads)); EXPECT_EQ(reads_size, trans->GetTotalReceivedBytes()); const HttpResponseInfo* response = trans->GetResponseInfo(); @@ -2125,7 +2276,10 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthKeepAlive) { std::string response_data; rv = ReadTransaction(trans.get(), &response_data); EXPECT_EQ(OK, rv); - int64 reads_size1 = ReadsSize(data_reads1, arraysize(data_reads1)); + + int64_t writes_size1 = CountWriteBytes(data_writes1, arraysize(data_writes1)); + EXPECT_EQ(writes_size1, trans->GetTotalSentBytes()); + int64_t reads_size1 = CountReadBytes(data_reads1, arraysize(data_reads1)); EXPECT_EQ(reads_size1, trans->GetTotalReceivedBytes()); } @@ -2392,8 +2546,8 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp10) { request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -2510,8 +2664,8 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAliveHttp11) { request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -2631,7 +2785,7 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp10) { request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -2738,7 +2892,7 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthProxyKeepAliveHttp11) { request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -2842,7 +2996,7 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) { request.load_flags = 0; // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -2902,7 +3056,7 @@ TEST_P(HttpNetworkTransactionTest, SanitizeProxyAuthHeaders) { request.load_flags = 0; // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3010,7 +3164,7 @@ TEST_P(HttpNetworkTransactionTest, request.method = "GET"; request.url = GURL("https://www.example.org/"); - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3075,8 +3229,7 @@ TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingNoPacTwoRequests) { request2.url = GURL("https://www.example.org/2"); // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("PROXY myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("PROXY myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3176,8 +3329,8 @@ TEST_P(HttpNetworkTransactionTest, HttpProxyLoadTimingWithPacTwoRequests) { request2.url = GURL("https://www.example.org/2"); // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3274,8 +3427,7 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxyGet) { request.url = GURL("http://www.example.org/"); // Configure against https proxy server "proxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed( - "https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3337,8 +3489,7 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGet) { request.load_flags = 0; // Configure against https proxy server "proxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed( - "https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3398,8 +3549,7 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithSessionRace) { request.load_flags = 0; // Configure SPDY proxy server "proxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3468,8 +3618,7 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) { request.load_flags = 0; // Configure against https proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("https://myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3569,8 +3718,7 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) { request.load_flags = 0; // Configure against https proxy server "proxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed( - "https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3654,8 +3802,7 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) { request.load_flags = 0; // Configure against https proxy server "proxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed( - "https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3746,8 +3893,7 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) { request.load_flags = 0; // Configure against https proxy server "proxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed( - "https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -3798,8 +3944,7 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) { TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsTwoServers) { // Configure against https proxy server "proxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed( - "https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session( @@ -3839,10 +3984,14 @@ TEST_P(HttpNetworkTransactionTest, // CONNECT to mail.example.org:443 via SPDY. SpdyHeaderBlock connect2_block; - connect2_block[spdy_util_.GetMethodKey()] = "CONNECT"; - connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443"; - connect2_block[spdy_util_.GetHostKey()] = "mail.example.org"; spdy_util_.MaybeAddVersionHeader(&connect2_block); + connect2_block[spdy_util_.GetMethodKey()] = "CONNECT"; + if (GetParam() == kProtoHTTP2) { + connect2_block[spdy_util_.GetHostKey()] = "mail.example.org:443"; + } else { + connect2_block[spdy_util_.GetHostKey()] = "mail.example.org"; + connect2_block[spdy_util_.GetPathKey()] = "mail.example.org:443"; + } scoped_ptr<SpdyFrame> connect2( spdy_util_.ConstructSpdySyn(3, connect2_block, LOWEST, false, false)); @@ -3937,8 +4086,7 @@ TEST_P(HttpNetworkTransactionTest, TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttpsLoadTimingTwoRequestsSameServer) { // Configure against https proxy server "proxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed( - "https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session( @@ -4061,8 +4209,7 @@ TEST_P(HttpNetworkTransactionTest, // Proxy to different servers. TEST_P(HttpNetworkTransactionTest, HttpsProxySpdyLoadTimingTwoHttpRequests) { // Configure against https proxy server "proxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed( - "https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session( @@ -4168,8 +4315,7 @@ TEST_P(HttpNetworkTransactionTest, HttpsProxyAuthRetry) { request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against https proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("https://myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -4268,7 +4414,7 @@ void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus( request.load_flags = 0; // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); // Since we have proxy, should try to establish tunnel. @@ -4486,7 +4632,7 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) { request.load_flags = 0; // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( @@ -4989,7 +5135,7 @@ TEST_P(HttpNetworkTransactionTest, request.load_flags = 0; // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -6305,7 +6451,7 @@ TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) { // Test HTTPS connections to a site with a bad certificate, going through a // proxy TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) { - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); HttpRequestInfo request; request.method = "GET"; @@ -6387,8 +6533,8 @@ TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) { // Test HTTPS connections to a site, going through an HTTPS proxy TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"); TestNetLog net_log; session_deps_.net_log = &net_log; @@ -6453,8 +6599,8 @@ TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) { // Test an HTTPS Proxy's ability to redirect a CONNECT request TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"); TestNetLog net_log; session_deps_.net_log = &net_log; @@ -6530,8 +6676,7 @@ TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) { // Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); HttpRequestInfo request; request.method = "GET"; @@ -6590,8 +6735,7 @@ TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) { // Test that an HTTPS proxy's response to a CONNECT request is filtered. TEST_P(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaHttpsProxy) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); HttpRequestInfo request; request.method = "GET"; @@ -6637,8 +6781,7 @@ TEST_P(HttpNetworkTransactionTest, // Test that a SPDY proxy's response to a CONNECT request is filtered. TEST_P(HttpNetworkTransactionTest, ErrorResponseToHttpsConnectViaSpdyProxy) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); HttpRequestInfo request; request.method = "GET"; @@ -6702,8 +6845,8 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthSpdyProxy) { request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against https proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -6843,8 +6986,8 @@ TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPush) { push_request.url = GURL("http://www.another-origin.com/foo.dat"); // Configure against https proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("HTTPS myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); @@ -6957,8 +7100,7 @@ TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) { request.url = GURL("http://www.example.org/"); // Configure against https proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("https://myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); @@ -7033,8 +7175,7 @@ TEST_P(HttpNetworkTransactionTest, CrossOriginProxyPushCorrectness) { // Test HTTPS connections to a site with a bad certificate, going through an // HTTPS proxy TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) { - session_deps_.proxy_service.reset(ProxyService::CreateFixed( - "https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); HttpRequestInfo request; request.method = "GET"; @@ -7163,7 +7304,7 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) { request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent, "Chromium Ultra Awesome X Edition"); - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -7323,11 +7464,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) { new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); MockWrite data_writes[] = { - MockWrite( - "HEAD / HTTP/1.1\r\n" - "Host: www.example.org\r\n" - "Connection: keep-alive\r\n" - "Content-Length: 0\r\n\r\n"), + MockWrite("HEAD / HTTP/1.1\r\n" + "Host: www.example.org\r\n" + "Connection: keep-alive\r\n\r\n"), }; // Lastly, the server responds with the actual content. @@ -7519,8 +7658,8 @@ TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) { request.url = GURL("http://www.example.org/"); request.load_flags = 0; - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"); TestNetLog net_log; session_deps_.net_log = &net_log; @@ -7578,8 +7717,8 @@ TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) { request.url = GURL("https://www.example.org/"); request.load_flags = 0; - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("SOCKS myproxy:1080"); TestNetLog net_log; session_deps_.net_log = &net_log; @@ -7642,8 +7781,8 @@ TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) { request.url = GURL("http://www.example.org/"); request.load_flags = 0; - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("socks4://myproxy:1080")); + session_deps_.proxy_service = + ProxyService::CreateFixed("socks4://myproxy:1080"); TestNetLog net_log; session_deps_.net_log = &net_log; @@ -7701,8 +7840,8 @@ TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) { request.url = GURL("http://www.example.org/"); request.load_flags = 0; - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"); TestNetLog net_log; session_deps_.net_log = &net_log; @@ -7773,8 +7912,8 @@ TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) { request.url = GURL("https://www.example.org/"); request.load_flags = 0; - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("SOCKS5 myproxy:1080"); TestNetLog net_log; session_deps_.net_log = &net_log; @@ -7864,8 +8003,10 @@ scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests( session->http_server_properties(); AlternativeService alternative_service( AlternateProtocolFromNextProto(next_proto), "", 443); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService( - HostPortPair("host.with.alternate", 80), alternative_service, 1.0); + HostPortPair("host.with.alternate", 80), alternative_service, 1.0, + expiration); return session; } @@ -7925,11 +8066,11 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) { }, }; - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; for (size_t i = 0; i < arraysize(tests); ++i) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixed(tests[i].proxy_server)); + session_deps_.proxy_service = + ProxyService::CreateFixed(tests[i].proxy_server); scoped_refptr<HttpNetworkSession> session( SetupSessionForGroupNameTests(GetParam(), &session_deps_)); @@ -7953,7 +8094,6 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) { EXPECT_EQ(tests[i].expected_group_name, transport_conn_pool->last_group_name_received()); } - } TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) { @@ -7988,11 +8128,11 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) { }, }; - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; for (size_t i = 0; i < arraysize(tests); ++i) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixed(tests[i].proxy_server)); + session_deps_.proxy_service = + ProxyService::CreateFixed(tests[i].proxy_server); scoped_refptr<HttpNetworkSession> session( SetupSessionForGroupNameTests(GetParam(), &session_deps_)); @@ -8058,11 +8198,11 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) { }, }; - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; for (size_t i = 0; i < arraysize(tests); ++i) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixed(tests[i].proxy_server)); + session_deps_.proxy_service = + ProxyService::CreateFixed(tests[i].proxy_server); scoped_refptr<HttpNetworkSession> session( SetupSessionForGroupNameTests(GetParam(), &session_deps_)); @@ -8099,8 +8239,8 @@ TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) { request.method = "GET"; request.url = GURL("http://www.example.org/"); - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("myproxy:70;foobar:80")); + session_deps_.proxy_service = + ProxyService::CreateFixed("myproxy:70;foobar:80"); // This simulates failure resolving all hostnames; that means we will fail // connecting to both proxies (myproxy:70 and foobar:80). @@ -8213,6 +8353,10 @@ TEST_P(HttpNetworkTransactionTest, RequestWriteError) { rv = callback.WaitForResult(); EXPECT_EQ(ERR_CONNECTION_RESET, rv); + + IPEndPoint endpoint; + EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint)); + EXPECT_LT(0u, endpoint.address().size()); } // Check that a connection closed after the start of the headers finishes ok. @@ -8252,6 +8396,10 @@ TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) { rv = ReadTransaction(trans.get(), &response_data); EXPECT_EQ(OK, rv); EXPECT_EQ("", response_data); + + IPEndPoint endpoint; + EXPECT_TRUE(trans->GetRemoteEndpoint(&endpoint)); + EXPECT_LT(0u, endpoint.address().size()); } // Make sure that a dropped connection while draining the body for auth @@ -8337,7 +8485,7 @@ TEST_P(HttpNetworkTransactionTest, DrainResetOK) { // Test HTTPS connections going through a proxy that sends extra data. TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) { - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); HttpRequestInfo request; request.method = "GET"; @@ -8556,7 +8704,6 @@ TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) { // Tests that changes to Auth realms are treated like auth rejections. TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) { - HttpRequestInfo request; request.method = "GET"; request.url = GURL("http://www.example.org/"); @@ -8711,18 +8858,207 @@ TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) { EXPECT_TRUE(response->auth_challenge.get() == NULL); } +TEST_P(HttpNetworkTransactionTest, HonorAlternativeServiceHeader) { + session_deps_.next_protos = SpdyNextProtos(); + session_deps_.use_alternative_services = true; + + std::string alternative_service_http_header = + GetAlternativeServiceHttpHeader(); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead(alternative_service_http_header.c_str()), + MockRead("\r\n"), + MockRead("hello world"), + MockRead(SYNCHRONOUS, OK), + }; + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.example.org/"); + request.load_flags = 0; + + StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); + + session_deps_.socket_factory->AddSocketDataProvider(&data); + + TestCompletionCallback callback; + + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + HostPortPair http_host_port_pair("www.example.org", 80); + HttpServerProperties& http_server_properties = + *session->http_server_properties(); + AlternativeServiceVector alternative_service_vector = + http_server_properties.GetAlternativeServices(http_host_port_pair); + EXPECT_TRUE(alternative_service_vector.empty()); + + EXPECT_EQ(OK, callback.WaitForResult()); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response != NULL); + ASSERT_TRUE(response->headers.get() != NULL); + EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + EXPECT_FALSE(response->was_fetched_via_spdy); + EXPECT_FALSE(response->was_npn_negotiated); + + std::string response_data; + ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); + EXPECT_EQ("hello world", response_data); + + alternative_service_vector = + http_server_properties.GetAlternativeServices(http_host_port_pair); + ASSERT_EQ(1u, alternative_service_vector.size()); + EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()), + alternative_service_vector[0].protocol); + EXPECT_EQ("www.example.com", alternative_service_vector[0].host); + EXPECT_EQ(443, alternative_service_vector[0].port); +} + +// Alternative Service headers must be ignored when |use_alternative_services| +// is false. +TEST_P(HttpNetworkTransactionTest, DoNotHonorAlternativeServiceHeader) { + session_deps_.next_protos = SpdyNextProtos(); + session_deps_.use_alternative_services = false; + + std::string alternative_service_http_header = + GetAlternativeServiceHttpHeader(); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead(alternative_service_http_header.c_str()), + MockRead("\r\n"), + MockRead("hello world"), + MockRead(SYNCHRONOUS, OK), + }; + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.example.org/"); + request.load_flags = 0; + + StaticSocketDataProvider data(data_reads, arraysize(data_reads), nullptr, 0); + + session_deps_.socket_factory->AddSocketDataProvider(&data); + + TestCompletionCallback callback; + + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + HostPortPair http_host_port_pair("www.example.org", 80); + HttpServerProperties& http_server_properties = + *session->http_server_properties(); + AlternativeServiceVector alternative_service_vector = + http_server_properties.GetAlternativeServices(http_host_port_pair); + EXPECT_TRUE(alternative_service_vector.empty()); + + EXPECT_EQ(OK, callback.WaitForResult()); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response != nullptr); + ASSERT_TRUE(response->headers.get() != nullptr); + EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + EXPECT_FALSE(response->was_fetched_via_spdy); + EXPECT_FALSE(response->was_npn_negotiated); + + std::string response_data; + ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); + EXPECT_EQ("hello world", response_data); + + alternative_service_vector = + http_server_properties.GetAlternativeServices(http_host_port_pair); + EXPECT_TRUE(alternative_service_vector.empty()); +} + +TEST_P(HttpNetworkTransactionTest, HonorMultipleAlternativeServiceHeader) { + session_deps_.next_protos = SpdyNextProtos(); + session_deps_.use_alternative_services = true; + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead("Alt-Svc: "), + MockRead(GetAlternateProtocolFromParam()), + MockRead("=\"www.example.com:443\";p=1.0,"), + MockRead("quic=\":1234\"\r\n\r\n"), + MockRead("hello world"), + MockRead(SYNCHRONOUS, OK), + }; + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.example.org/"); + request.load_flags = 0; + + StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); + + session_deps_.socket_factory->AddSocketDataProvider(&data); + + TestCompletionCallback callback; + + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + HostPortPair http_host_port_pair("www.example.org", 80); + HttpServerProperties& http_server_properties = + *session->http_server_properties(); + AlternativeServiceVector alternative_service_vector = + http_server_properties.GetAlternativeServices(http_host_port_pair); + EXPECT_TRUE(alternative_service_vector.empty()); + + EXPECT_EQ(OK, callback.WaitForResult()); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response != NULL); + ASSERT_TRUE(response->headers.get() != NULL); + EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + EXPECT_FALSE(response->was_fetched_via_spdy); + EXPECT_FALSE(response->was_npn_negotiated); + + std::string response_data; + ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); + EXPECT_EQ("hello world", response_data); + + alternative_service_vector = + http_server_properties.GetAlternativeServices(http_host_port_pair); + ASSERT_EQ(2u, alternative_service_vector.size()); + EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()), + alternative_service_vector[0].protocol); + EXPECT_EQ("www.example.com", alternative_service_vector[0].host); + EXPECT_EQ(443, alternative_service_vector[0].port); + EXPECT_EQ(QUIC, alternative_service_vector[1].protocol); + EXPECT_EQ("www.example.org", alternative_service_vector[1].host); + EXPECT_EQ(1234, alternative_service_vector[1].port); +} + +// Alternate Protocol headers must be honored even if |use_alternative_services| +// is false. TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) { session_deps_.next_protos = SpdyNextProtos(); - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = false; std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader(); MockRead data_reads[] = { - MockRead("HTTP/1.1 200 OK\r\n"), - MockRead(alternate_protocol_http_header.c_str()), - MockRead("hello world"), - MockRead(SYNCHRONOUS, OK), + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead(alternate_protocol_http_header.c_str()), + MockRead("\r\n"), + MockRead("hello world"), + MockRead(SYNCHRONOUS, OK), }; HttpRequestInfo request; @@ -8773,7 +9109,7 @@ TEST_P(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) { TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) { session_deps_.next_protos = SpdyNextProtos(); - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; MockRead data_reads[] = { MockRead("HTTP/1.1 200 OK\r\n"), @@ -8799,8 +9135,9 @@ TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) { HttpServerProperties& http_server_properties = *session->http_server_properties(); AlternativeService alternative_service(QUIC, "", 80); - http_server_properties.SetAlternativeService(http_host_port_pair, - alternative_service, 1.0); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); + http_server_properties.SetAlternativeService( + http_host_port_pair, alternative_service, 1.0, expiration); AlternativeServiceVector alternative_service_vector = http_server_properties.GetAlternativeServices(http_host_port_pair); @@ -8831,9 +9168,117 @@ TEST_P(HttpNetworkTransactionTest, EmptyAlternateProtocolHeader) { EXPECT_TRUE(alternative_service_vector.empty()); } +TEST_P(HttpNetworkTransactionTest, AltSvcOverwritesAlternateProtocol) { + session_deps_.next_protos = SpdyNextProtos(); + session_deps_.use_alternative_services = true; + + std::string alternative_service_http_header = + GetAlternativeServiceHttpHeader(); + std::string alternate_protocol_http_header = GetAlternateProtocolHttpHeader(); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead(alternative_service_http_header.c_str()), + MockRead(alternate_protocol_http_header.c_str()), + MockRead("\r\n"), + MockRead("hello world"), + MockRead(SYNCHRONOUS, OK), + }; + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.example.org/"); + request.load_flags = 0; + + StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); + + session_deps_.socket_factory->AddSocketDataProvider(&data); + + TestCompletionCallback callback; + + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + HostPortPair http_host_port_pair("www.example.org", 80); + HttpServerProperties& http_server_properties = + *session->http_server_properties(); + AlternativeServiceVector alternative_service_vector = + http_server_properties.GetAlternativeServices(http_host_port_pair); + EXPECT_TRUE(alternative_service_vector.empty()); + + EXPECT_EQ(OK, callback.WaitForResult()); + + const HttpResponseInfo* response = trans->GetResponseInfo(); + ASSERT_TRUE(response != NULL); + ASSERT_TRUE(response->headers.get() != NULL); + EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); + EXPECT_FALSE(response->was_fetched_via_spdy); + EXPECT_FALSE(response->was_npn_negotiated); + + std::string response_data; + ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data)); + EXPECT_EQ("hello world", response_data); + + alternative_service_vector = + http_server_properties.GetAlternativeServices(http_host_port_pair); + ASSERT_EQ(1u, alternative_service_vector.size()); + EXPECT_EQ(AlternateProtocolFromNextProto(GetParam()), + alternative_service_vector[0].protocol); + EXPECT_EQ("www.example.com", alternative_service_vector[0].host); + EXPECT_EQ(443, alternative_service_vector[0].port); +} + +// When |use_alternative_services| is false, do not observe alternative service +// entries that point to a different host. +TEST_P(HttpNetworkTransactionTest, DisableAlternativeServiceToDifferentHost) { + session_deps_.use_alternative_services = false; + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://www.example.org/"); + request.load_flags = 0; + + MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); + StaticSocketDataProvider first_data; + first_data.set_connect_data(mock_connect); + session_deps_.socket_factory->AddSocketDataProvider(&first_data); + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"), + MockRead(ASYNC, OK), + }; + StaticSocketDataProvider second_data(data_reads, arraysize(data_reads), + nullptr, 0); + session_deps_.socket_factory->AddSocketDataProvider(&second_data); + + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + + base::WeakPtr<HttpServerProperties> http_server_properties = + session->http_server_properties(); + AlternativeService alternative_service( + AlternateProtocolFromNextProto(GetParam()), "different.example.org", 80); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); + http_server_properties->SetAlternativeService( + HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration); + + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + TestCompletionCallback callback; + + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + // The connetion to origin was refused, and the alternative service should not + // be used (even though mock data are there), therefore the request should + // fail. + EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.GetResult(rv)); +} + TEST_P(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) { - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; HttpRequestInfo request; request.method = "GET"; @@ -8864,8 +9309,9 @@ TEST_P(HttpNetworkTransactionTest, const AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), "www.example.org", 666); // Port is ignored by MockConnect anyway. - http_server_properties->SetAlternativeService(host_port_pair, - alternative_service, 1.0); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); + http_server_properties->SetAlternativeService( + host_port_pair, alternative_service, 1.0, expiration); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -8892,13 +9338,13 @@ TEST_P(HttpNetworkTransactionTest, alternative_service_vector[0])); } +// Ensure that we are not allowed to redirect traffic via an alternate protocol +// to an unrestricted (port >= 1024) when the original traffic was on a +// restricted port (port < 1024). Ensure that we can redirect in all other +// cases. TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) { - // Ensure that we're not allowed to redirect traffic via an alternate - // protocol to an unrestricted (port >= 1024) when the original traffic was - // on a restricted port (port < 1024). Ensure that we can redirect in all - // other cases. - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; HttpRequestInfo restricted_port_request; restricted_port_request.method = "GET"; @@ -8927,9 +9373,10 @@ TEST_P(HttpNetworkTransactionTest, AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), "www.example.org", kUnrestrictedAlternatePort); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService( HostPortPair::FromURL(restricted_port_request.url), alternative_service, - 1.0); + 1.0, expiration); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -8943,14 +9390,12 @@ TEST_P(HttpNetworkTransactionTest, EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult()); } +// Ensure that we are allowed to redirect traffic via an alternate protocol to +// an unrestricted (port >= 1024) when the original traffic was on a restricted +// port (port < 1024) if we set |enable_user_alternate_protocol_ports|. TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedPermitted) { - // Ensure that we're allowed to redirect traffic via an alternate - // protocol to an unrestricted (port >= 1024) when the original traffic was - // on a restricted port (port < 1024) if we set - // enable_user_alternate_protocol_ports. - - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.enable_user_alternate_protocol_ports = true; HttpRequestInfo restricted_port_request; @@ -8980,9 +9425,10 @@ TEST_P(HttpNetworkTransactionTest, AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), "www.example.org", kUnrestrictedAlternatePort); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService( HostPortPair::FromURL(restricted_port_request.url), alternative_service, - 1.0); + 1.0, expiration); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -8995,13 +9441,13 @@ TEST_P(HttpNetworkTransactionTest, EXPECT_EQ(OK, callback.WaitForResult()); } +// Ensure that we are not allowed to redirect traffic via an alternate protocol +// to an unrestricted (port >= 1024) when the original traffic was on a +// restricted port (port < 1024). Ensure that we can redirect in all other +// cases. TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) { - // Ensure that we're not allowed to redirect traffic via an alternate - // protocol to an unrestricted (port >= 1024) when the original traffic was - // on a restricted port (port < 1024). Ensure that we can redirect in all - // other cases. - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; HttpRequestInfo restricted_port_request; restricted_port_request.method = "GET"; @@ -9030,9 +9476,10 @@ TEST_P(HttpNetworkTransactionTest, AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), "www.example.org", kRestrictedAlternatePort); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService( HostPortPair::FromURL(restricted_port_request.url), alternative_service, - 1.0); + 1.0, expiration); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -9046,13 +9493,13 @@ TEST_P(HttpNetworkTransactionTest, EXPECT_EQ(OK, callback.WaitForResult()); } +// Ensure that we are not allowed to redirect traffic via an alternate protocol +// to an unrestricted (port >= 1024) when the original traffic was on a +// restricted port (port < 1024). Ensure that we can redirect in all other +// cases. TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) { - // Ensure that we're not allowed to redirect traffic via an alternate - // protocol to an unrestricted (port >= 1024) when the original traffic was - // on a restricted port (port < 1024). Ensure that we can redirect in all - // other cases. - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; HttpRequestInfo unrestricted_port_request; unrestricted_port_request.method = "GET"; @@ -9081,9 +9528,10 @@ TEST_P(HttpNetworkTransactionTest, AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), "www.example.org", kRestrictedAlternatePort); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService( HostPortPair::FromURL(unrestricted_port_request.url), alternative_service, - 1.0); + 1.0, expiration); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -9096,13 +9544,13 @@ TEST_P(HttpNetworkTransactionTest, EXPECT_EQ(OK, callback.WaitForResult()); } +// Ensure that we are not allowed to redirect traffic via an alternate protocol +// to an unrestricted (port >= 1024) when the original traffic was on a +// restricted port (port < 1024). Ensure that we can redirect in all other +// cases. TEST_P(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) { - // Ensure that we're not allowed to redirect traffic via an alternate - // protocol to an unrestricted (port >= 1024) when the original traffic was - // on a restricted port (port < 1024). Ensure that we can redirect in all - // other cases. - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; HttpRequestInfo unrestricted_port_request; unrestricted_port_request.method = "GET"; @@ -9127,13 +9575,14 @@ TEST_P(HttpNetworkTransactionTest, base::WeakPtr<HttpServerProperties> http_server_properties = session->http_server_properties(); - const int kUnrestrictedAlternatePort = 1024; + const int kUnrestrictedAlternatePort = 1025; AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), "www.example.org", kUnrestrictedAlternatePort); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService( HostPortPair::FromURL(unrestricted_port_request.url), alternative_service, - 1.0); + 1.0, expiration); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -9146,11 +9595,11 @@ TEST_P(HttpNetworkTransactionTest, EXPECT_EQ(OK, callback.WaitForResult()); } +// Ensure that we are not allowed to redirect traffic via an alternate protocol +// to an unsafe port, and that we resume the second HttpStreamFactoryImpl::Job +// once the alternate protocol request fails. TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) { - // Ensure that we're not allowed to redirect traffic via an alternate - // protocol to an unsafe port, and that we resume the second - // HttpStreamFactoryImpl::Job once the alternate protocol request fails. - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; HttpRequestInfo request; request.method = "GET"; @@ -9176,8 +9625,9 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) { AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), "www.example.org", kUnsafePort); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService( - HostPortPair::FromURL(request.url), alternative_service, 1.0); + HostPortPair::FromURL(request.url), alternative_service, 1.0, expiration); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -9188,9 +9638,6 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) { // The HTTP request should succeed. EXPECT_EQ(OK, callback.WaitForResult()); - // Disable alternate protocol before the asserts. - // HttpStreamFactory::set_use_alternate_protocols(false); - const HttpResponseInfo* response = trans->GetResponseInfo(); ASSERT_TRUE(response != NULL); ASSERT_TRUE(response->headers.get() != NULL); @@ -9202,7 +9649,7 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) { } TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) { - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.next_protos = SpdyNextProtos(); HttpRequestInfo request; @@ -9214,12 +9661,12 @@ TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) { GetAlternateProtocolHttpHeader(); MockRead data_reads[] = { - MockRead("HTTP/1.1 200 OK\r\n"), - MockRead(alternate_protocol_http_header.c_str()), - MockRead("hello world"), - MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), - MockRead(ASYNC, OK) - }; + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead(alternate_protocol_http_header.c_str()), + MockRead("\r\n"), + MockRead("hello world"), + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), + MockRead(ASYNC, OK)}; StaticSocketDataProvider first_transaction( data_reads, arraysize(data_reads), NULL, 0); @@ -9290,7 +9737,7 @@ TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) { } TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) { - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.next_protos = SpdyNextProtos(); HttpRequestInfo request; @@ -9302,11 +9749,12 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) { GetAlternateProtocolHttpHeader(); MockRead data_reads[] = { - MockRead("HTTP/1.1 200 OK\r\n"), - MockRead(alternate_protocol_http_header.c_str()), - MockRead("hello world"), - MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), - MockRead(ASYNC, OK), + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead(alternate_protocol_http_header.c_str()), + MockRead("\r\n"), + MockRead("hello world"), + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), + MockRead(ASYNC, OK), }; StaticSocketDataProvider first_transaction( @@ -9406,7 +9854,7 @@ TEST_P(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) { } TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) { - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.next_protos = SpdyNextProtos(); HttpRequestInfo request; @@ -9418,11 +9866,12 @@ TEST_P(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) { GetAlternateProtocolHttpHeader(); MockRead data_reads[] = { - MockRead("HTTP/1.1 200 OK\r\n"), - MockRead(alternate_protocol_http_header.c_str()), - MockRead("hello world"), - MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), - MockRead(ASYNC, OK), + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead(alternate_protocol_http_header.c_str()), + MockRead("\r\n"), + MockRead("hello world"), + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), + MockRead(ASYNC, OK), }; StaticSocketDataProvider first_transaction( @@ -9532,7 +9981,7 @@ class CapturingProxyResolverFactory : public ProxyResolverFactory { TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) { - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.next_protos = SpdyNextProtos(); ProxyConfig proxy_config; @@ -9541,7 +9990,7 @@ TEST_P(HttpNetworkTransactionTest, CapturingProxyResolver capturing_proxy_resolver; session_deps_.proxy_service.reset(new ProxyService( - new ProxyConfigServiceFixed(proxy_config), + make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)), make_scoped_ptr( new CapturingProxyResolverFactory(&capturing_proxy_resolver)), NULL)); @@ -9557,11 +10006,12 @@ TEST_P(HttpNetworkTransactionTest, GetAlternateProtocolHttpHeader(); MockRead data_reads[] = { - MockRead("HTTP/1.1 200 OK\r\n"), - MockRead(alternate_protocol_http_header.c_str()), - MockRead("hello world"), - MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), - MockRead(ASYNC, OK), + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead(alternate_protocol_http_header.c_str()), + MockRead("\r\n"), + MockRead("hello world"), + MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ), + MockRead(ASYNC, OK), }; StaticSocketDataProvider first_transaction( @@ -9657,7 +10107,7 @@ TEST_P(HttpNetworkTransactionTest, TEST_P(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdyWithExistingSpdySession) { - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.next_protos = SpdyNextProtos(); HttpRequestInfo request; @@ -9669,10 +10119,11 @@ TEST_P(HttpNetworkTransactionTest, GetAlternateProtocolHttpHeader(); MockRead data_reads[] = { - MockRead("HTTP/1.1 200 OK\r\n"), - MockRead(alternate_protocol_http_header.c_str()), - MockRead("hello world"), - MockRead(ASYNC, OK), + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead(alternate_protocol_http_header.c_str()), + MockRead("\r\n"), + MockRead("hello world"), + MockRead(ASYNC, OK), }; StaticSocketDataProvider first_transaction( @@ -10082,10 +10533,10 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) { auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER); } if (test_config.proxy_url) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixed(test_config.proxy_url)); + session_deps_.proxy_service = + ProxyService::CreateFixed(test_config.proxy_url); } else { - session_deps_.proxy_service.reset(ProxyService::CreateDirect()); + session_deps_.proxy_service = ProxyService::CreateDirect(); } HttpRequestInfo request; @@ -10172,7 +10623,7 @@ TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) { HttpAuthHandlerMock::Factory* auth_factory( new HttpAuthHandlerMock::Factory()); session_deps_.http_auth_handler_factory.reset(auth_factory); - session_deps_.proxy_service.reset(ProxyService::CreateDirect()); + session_deps_.proxy_service = ProxyService::CreateDirect(); session_deps_.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1"); session_deps_.host_resolver->set_synchronous_mode(true); @@ -10354,7 +10805,7 @@ TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) { // This tests the case that a request is issued via http instead of spdy after // npn is negotiated. TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) { - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; NextProtoVector next_protos; next_protos.push_back(kProtoHTTP11); session_deps_.next_protos = next_protos; @@ -10375,10 +10826,11 @@ TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) { GetAlternateProtocolHttpHeader(); MockRead data_reads[] = { - MockRead("HTTP/1.1 200 OK\r\n"), - MockRead(alternate_protocol_http_header.c_str()), - MockRead("hello world"), - MockRead(SYNCHRONOUS, OK), + MockRead("HTTP/1.1 200 OK\r\n"), + MockRead(alternate_protocol_http_header.c_str()), + MockRead("\r\n"), + MockRead("hello world"), + MockRead(SYNCHRONOUS, OK), }; SSLSocketDataProvider ssl(ASYNC, OK); @@ -10414,11 +10866,11 @@ TEST_P(HttpNetworkTransactionTest, NpnWithHttpOverSSL) { EXPECT_TRUE(response->was_npn_negotiated); } +// Simulate the SSL handshake completing with an NPN negotiation followed by an +// immediate server closing of the socket. +// Regression test for https://crbug.com/46369. TEST_P(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) { - // Simulate the SSL handshake completing with an NPN negotiation - // followed by an immediate server closing of the socket. - // Fix crash: http://crbug.com/46369 - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.next_protos = SpdyNextProtos(); HttpRequestInfo request; @@ -10476,14 +10928,14 @@ class UrlRecordingHttpAuthHandlerMock : public HttpAuthHandlerMock { GURL* url_; }; +// This test ensures that the URL passed into the proxy is upgraded to https +// when doing an Alternate Protocol upgrade. TEST_P(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) { - // This test ensures that the URL passed into the proxy is upgraded - // to https when doing an Alternate Protocol upgrade. - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.next_protos = SpdyNextProtos(); - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"); TestNetLog net_log; session_deps_.net_log = &net_log; GURL request_url; @@ -10731,8 +11183,8 @@ TEST_P(HttpNetworkTransactionTest, CancelAfterHeaders) { // Test a basic GET request through a proxy. TEST_P(HttpNetworkTransactionTest, ProxyGet) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -10795,8 +11247,8 @@ TEST_P(HttpNetworkTransactionTest, ProxyGet) { // Test a basic HTTPS GET request through a proxy. TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -10873,7 +11325,7 @@ TEST_P(HttpNetworkTransactionTest, ProxyTunnelGet) { // Test a basic HTTPS GET request through a proxy, but the server hangs up // while establishing the tunnel. TEST_P(HttpNetworkTransactionTest, ProxyTunnelGetHangup) { - session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("myproxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -11244,8 +11696,7 @@ TEST_P(HttpNetworkTransactionTest, // The test is repeated twice, first for connecting to an HTTPS endpoint, // then for connecting to an HTTP endpoint. TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) { - session_deps_.proxy_service.reset( - ProxyService::CreateFixed("https://proxy:70")); + session_deps_.proxy_service = ProxyService::CreateFixed("https://proxy:70"); BoundTestNetLog log; session_deps_.net_log = log.bound().net_log(); @@ -11336,7 +11787,7 @@ TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) { } TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) { - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.next_protos = SpdyNextProtos(); // Set up a special HttpNetworkSession with a MockCachingHostResolver. @@ -11435,7 +11886,7 @@ TEST_P(HttpNetworkTransactionTest, UseIPConnectionPooling) { } TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingAfterResolution) { - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.next_protos = SpdyNextProtos(); // Set up a special HttpNetworkSession with a MockCachingHostResolver. @@ -11562,7 +12013,7 @@ class OneTimeCachingHostResolver : public HostResolver { TEST_P(HttpNetworkTransactionTest, UseIPConnectionPoolingWithHostCacheExpiration) { - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; session_deps_.next_protos = SpdyNextProtos(); // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver. @@ -11821,14 +12272,15 @@ class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest { data_refused.set_connect_data(mock_connect); session_deps_.socket_factory->AddSocketDataProvider(&data_refused); - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); base::WeakPtr<HttpServerProperties> http_server_properties = session->http_server_properties(); AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), alternative); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService(origin, alternative_service, - 1.0); + 1.0, expiration); // First request to alternative. if (pooling) { @@ -11877,7 +12329,6 @@ class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest { INSTANTIATE_TEST_CASE_P(NextProto, AltSvcCertificateVerificationTest, testing::Values(kProtoSPDY31, - kProtoHTTP2_14, kProtoHTTP2)); // The alternative service host must exhibit a certificate that is valid for the @@ -11925,14 +12376,15 @@ TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) { session_deps_.socket_factory->AddSocketDataProvider(&data_refused); // Set up alternative service for origin. - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); base::WeakPtr<HttpServerProperties> http_server_properties = session->http_server_properties(); AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), alternative); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService(origin, alternative_service, - 1.0); + 1.0, expiration); scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); @@ -11997,14 +12449,15 @@ TEST_P(HttpNetworkTransactionTest, FailedAlternativeServiceIsNotUserVisible) { session_deps_.socket_factory->AddSocketDataProvider(&http_data); // Set up alternative service for origin. - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); base::WeakPtr<HttpServerProperties> http_server_properties = session->http_server_properties(); AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), alternative); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService(origin, alternative_service, - 1.0); + 1.0, expiration); HttpNetworkTransaction trans1(DEFAULT_PRIORITY, session.get()); HttpRequestInfo request1; @@ -12105,14 +12558,15 @@ TEST_P(HttpNetworkTransactionTest, AlternativeServiceShouldNotPoolToHttp11) { session_deps_.socket_factory->AddSocketDataProvider(&data_refused); // Set up alternative service for origin. - session_deps_.use_alternate_protocols = true; + session_deps_.use_alternative_services = true; scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); base::WeakPtr<HttpServerProperties> http_server_properties = session->http_server_properties(); AlternativeService alternative_service( AlternateProtocolFromNextProto(GetParam()), alternative); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); http_server_properties->SetAlternativeService(origin, alternative_service, - 1.0); + 1.0, expiration); // First transaction to alternative to open an HTTP/1.1 socket. scoped_ptr<HttpTransaction> trans1( @@ -12189,11 +12643,11 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) { // SPDY GET for HTTP URL (through the proxy, but not the tunnel). SpdyHeaderBlock req2_block; + spdy_util_.MaybeAddVersionHeader(&req2_block); req2_block[spdy_util_.GetMethodKey()] = "GET"; - req2_block[spdy_util_.GetPathKey()] = "/"; req2_block[spdy_util_.GetHostKey()] = "www.example.org:8080"; req2_block[spdy_util_.GetSchemeKey()] = "http"; - spdy_util_.MaybeAddVersionHeader(&req2_block); + req2_block[spdy_util_.GetPathKey()] = "/"; scoped_ptr<SpdyFrame> req2( spdy_util_.ConstructSpdySyn(3, req2_block, MEDIUM, false, true)); @@ -12227,8 +12681,8 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionForHttpOverTunnel) { MockConnect connect_data1(ASYNC, OK); data1.set_connect_data(connect_data1); - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("HTTPS proxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("HTTPS proxy:70"); TestNetLog log; session_deps_.net_log = &log; SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy @@ -12308,9 +12762,9 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) { scoped_ptr<SpdyFrame> resp1(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); scoped_ptr<SpdyFrame> body1(spdy_util_.ConstructSpdyBodyFrame(1, true)); MockRead reads1[] = { - CreateMockRead(*resp1, 1), - CreateMockRead(*body1, 2), - MockRead(ASYNC, OK, 3) // EOF + CreateMockRead(*resp1, 1), + CreateMockRead(*body1, 2), + MockRead(ASYNC, OK, 3) // EOF }; scoped_ptr<DeterministicSocketData> data1( @@ -12333,9 +12787,9 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) { scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); scoped_ptr<SpdyFrame> body2(spdy_util_.ConstructSpdyBodyFrame(1, true)); MockRead reads2[] = { - CreateMockRead(*resp2, 1), - CreateMockRead(*body2, 2), - MockRead(ASYNC, OK, 3) // EOF + CreateMockRead(*resp2, 1), + CreateMockRead(*body2, 2), + MockRead(ASYNC, OK, 3) // EOF }; scoped_ptr<DeterministicSocketData> data2( @@ -12349,7 +12803,8 @@ TEST_P(HttpNetworkTransactionTest, DoNotUseSpdySessionIfCertDoesNotMatch) { ProxyConfig proxy_config; proxy_config.proxy_rules().ParseFromString("http=https://proxy:443"); session_deps_.proxy_service.reset(new ProxyService( - new ProxyConfigServiceFixed(proxy_config), nullptr, NULL)); + make_scoped_ptr(new ProxyConfigServiceFixed(proxy_config)), nullptr, + NULL)); SSLSocketDataProvider ssl1(ASYNC, OK); // to the proxy ssl1.SetNextProto(GetParam()); @@ -12651,7 +13106,7 @@ TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) { scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); - MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED); + MockConnect mock_connect(SYNCHRONOUS, ERR_NAME_NOT_RESOLVED); StaticSocketDataProvider data; data.set_connect_data(mock_connect); session_deps_.socket_factory->AddSocketDataProvider(&data); @@ -12662,7 +13117,7 @@ TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) { EXPECT_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); - EXPECT_EQ(ERR_CONNECTION_REFUSED, rv); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); // We don't care whether this succeeds or fails, but it shouldn't crash. HttpRequestHeaders request_headers; @@ -12671,7 +13126,11 @@ TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) { ConnectionAttempts attempts; trans->GetConnectionAttempts(&attempts); ASSERT_EQ(1u, attempts.size()); - EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result); + + IPEndPoint endpoint; + EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint)); + EXPECT_TRUE(endpoint.address().empty()); } TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) { @@ -12684,7 +13143,7 @@ TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) { scoped_ptr<HttpTransaction> trans( new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); - MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); + MockConnect mock_connect(ASYNC, ERR_NAME_NOT_RESOLVED); StaticSocketDataProvider data; data.set_connect_data(mock_connect); session_deps_.socket_factory->AddSocketDataProvider(&data); @@ -12695,7 +13154,7 @@ TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) { EXPECT_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); - EXPECT_EQ(ERR_CONNECTION_REFUSED, rv); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv); // We don't care whether this succeeds or fails, but it shouldn't crash. HttpRequestHeaders request_headers; @@ -12704,7 +13163,11 @@ TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) { ConnectionAttempts attempts; trans->GetConnectionAttempts(&attempts); ASSERT_EQ(1u, attempts.size()); - EXPECT_EQ(ERR_CONNECTION_REFUSED, attempts[0].result); + EXPECT_EQ(ERR_NAME_NOT_RESOLVED, attempts[0].result); + + IPEndPoint endpoint; + EXPECT_FALSE(trans->GetRemoteEndpoint(&endpoint)); + EXPECT_TRUE(endpoint.address().empty()); } TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) { @@ -12937,8 +13400,6 @@ class FakeStream : public HttpStream, return false; } - bool CanFindEndOfResponse() const override { return false; } - bool IsConnectionReused() const override { ADD_FAILURE(); return false; @@ -12946,12 +13407,14 @@ class FakeStream : public HttpStream, void SetConnectionReused() override { ADD_FAILURE(); } - bool IsConnectionReusable() const override { + bool CanReuseConnection() const override { return false; } + + int64_t GetTotalReceivedBytes() const override { ADD_FAILURE(); - return false; + return 0; } - int64 GetTotalReceivedBytes() const override { + int64_t GetTotalSentBytes() const override { ADD_FAILURE(); return 0; } @@ -12967,10 +13430,7 @@ class FakeStream : public HttpStream, ADD_FAILURE(); } - bool IsSpdyHttpStream() const override { - ADD_FAILURE(); - return false; - } + bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; } void Drain(HttpNetworkSession* session) override { ADD_FAILURE(); } @@ -13094,7 +13554,6 @@ class FakeStreamFactory : public HttpStreamFactory { void PreconnectStreams(int num_streams, const HttpRequestInfo& info, - RequestPriority priority, const SSLConfig& server_ssl_config, const SSLConfig& proxy_ssl_config) override { ADD_FAILURE(); @@ -13160,22 +13619,20 @@ class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase { return false; } - bool CanFindEndOfResponse() const override { - return parser()->CanFindEndOfResponse(); - } - bool IsConnectionReused() const override { NOTREACHED(); return false; } void SetConnectionReused() override { NOTREACHED(); } - bool IsConnectionReusable() const override { + bool CanReuseConnection() const override { return false; } + + int64_t GetTotalReceivedBytes() const override { NOTREACHED(); - return false; + return 0; } - int64 GetTotalReceivedBytes() const override { + int64_t GetTotalSentBytes() const override { NOTREACHED(); return 0; } @@ -13191,10 +13648,7 @@ class FakeWebSocketBasicHandshakeStream : public WebSocketHandshakeStreamBase { NOTREACHED(); } - bool IsSpdyHttpStream() const override { - NOTREACHED(); - return false; - } + bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; } void Drain(HttpNetworkSession* session) override { NOTREACHED(); } @@ -13504,8 +13958,8 @@ TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest2) { HttpStreamFactory* http_stream_factory = session->http_stream_factory(); SSLConfig ssl_config; session->ssl_config_service()->GetSSLConfig(&ssl_config); - http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY, - ssl_config, ssl_config); + http_stream_factory->PreconnectStreams(1, ssl_request, ssl_config, + ssl_config); EXPECT_EQ(0, GetIdleSocketCountInSSLSocketPool(session.get())); // Start the HTTP request. Pool should stall. @@ -14007,8 +14461,8 @@ TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWssTunnel) { AddWebSocketHeaders(&request.extra_headers); // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -14113,8 +14567,8 @@ TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) { AddWebSocketHeaders(&request.extra_headers); // Configure against proxy server "myproxy:70". - session_deps_.proxy_service.reset( - ProxyService::CreateFixedFromPacResult("PROXY myproxy:70")); + session_deps_.proxy_service = + ProxyService::CreateFixedFromPacResult("PROXY myproxy:70"); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -14182,4 +14636,145 @@ TEST_P(HttpNetworkTransactionTest, ProxyHeadersNotSentOverWsTunnel) { session->CloseAllConnections(); } +TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost) { + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("foo", 3)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("http://www.foo.com/"); + request.upload_data_stream = &upload_data_stream; + + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + MockWrite data_writes[] = { + MockWrite("POST / HTTP/1.1\r\n" + "Host: www.foo.com\r\n" + "Connection: keep-alive\r\n" + "Content-Length: 3\r\n\r\n"), + MockWrite("foo"), + }; + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"), + MockRead(SYNCHRONOUS, OK), + }; + StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, + arraysize(data_writes)); + session_deps_.socket_factory->AddSocketDataProvider(&data); + + TestCompletionCallback callback; + + EXPECT_EQ(ERR_IO_PENDING, + trans->Start(&request, callback.callback(), BoundNetLog())); + EXPECT_EQ(OK, callback.WaitForResult()); + + std::string response_data; + EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data)); + + EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)), + trans->GetTotalSentBytes()); + EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)), + trans->GetTotalReceivedBytes()); +} + +TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesPost100Continue) { + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("foo", 3)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("http://www.foo.com/"); + request.upload_data_stream = &upload_data_stream; + + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + MockWrite data_writes[] = { + MockWrite("POST / HTTP/1.1\r\n" + "Host: www.foo.com\r\n" + "Connection: keep-alive\r\n" + "Content-Length: 3\r\n\r\n"), + MockWrite("foo"), + }; + + MockRead data_reads[] = { + MockRead("HTTP/1.1 100 Continue\r\n\r\n"), + MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"), + MockRead(SYNCHRONOUS, OK), + }; + StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, + arraysize(data_writes)); + session_deps_.socket_factory->AddSocketDataProvider(&data); + + TestCompletionCallback callback; + + EXPECT_EQ(ERR_IO_PENDING, + trans->Start(&request, callback.callback(), BoundNetLog())); + EXPECT_EQ(OK, callback.WaitForResult()); + + std::string response_data; + EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data)); + + EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)), + trans->GetTotalSentBytes()); + EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)), + trans->GetTotalReceivedBytes()); +} + +TEST_P(HttpNetworkTransactionTest, TotalNetworkBytesChunkedPost) { + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("foo", 3)); + ChunkedUploadDataStream upload_data_stream(0); + + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("http://www.foo.com/"); + request.upload_data_stream = &upload_data_stream; + + scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); + scoped_ptr<HttpTransaction> trans( + new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); + // Send headers successfully, but get an error while sending the body. + MockWrite data_writes[] = { + MockWrite("POST / HTTP/1.1\r\n" + "Host: www.foo.com\r\n" + "Connection: keep-alive\r\n" + "Transfer-Encoding: chunked\r\n\r\n"), + MockWrite("1\r\nf\r\n"), MockWrite("2\r\noo\r\n"), MockWrite("0\r\n\r\n"), + }; + + MockRead data_reads[] = { + MockRead("HTTP/1.1 200 OK\r\n\r\n"), MockRead("hello world"), + MockRead(SYNCHRONOUS, OK), + }; + StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes, + arraysize(data_writes)); + session_deps_.socket_factory->AddSocketDataProvider(&data); + + TestCompletionCallback callback; + + EXPECT_EQ(ERR_IO_PENDING, + trans->Start(&request, callback.callback(), BoundNetLog())); + + base::RunLoop().RunUntilIdle(); + upload_data_stream.AppendData("f", 1, false); + + base::RunLoop().RunUntilIdle(); + upload_data_stream.AppendData("oo", 2, true); + + EXPECT_EQ(OK, callback.WaitForResult()); + + std::string response_data; + EXPECT_EQ(OK, ReadTransaction(trans.get(), &response_data)); + + EXPECT_EQ(CountWriteBytes(data_writes, arraysize(data_writes)), + trans->GetTotalSentBytes()); + EXPECT_EQ(CountReadBytes(data_reads, arraysize(data_reads)), + trans->GetTotalReceivedBytes()); +} + } // namespace net diff --git a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc index 4fdebb2b22c..6b44dbbee49 100644 --- a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc @@ -326,10 +326,6 @@ INSTANTIATE_TEST_CASE_P( ::testing::Values(HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY31), HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY31), HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY31), - HttpProxyClientSocketPoolTestParams(HTTP, kProtoHTTP2_14), - HttpProxyClientSocketPoolTestParams(HTTPS, - kProtoHTTP2_14), - HttpProxyClientSocketPoolTestParams(SPDY, kProtoHTTP2_14), HttpProxyClientSocketPoolTestParams(HTTP, kProtoHTTP2), HttpProxyClientSocketPoolTestParams(HTTPS, kProtoHTTP2), HttpProxyClientSocketPoolTestParams(SPDY, kProtoHTTP2))); diff --git a/chromium/net/http/http_request_headers.cc b/chromium/net/http/http_request_headers.cc index 004d0659512..c2eee59af95 100644 --- a/chromium/net/http/http_request_headers.cc +++ b/chromium/net/http/http_request_headers.cc @@ -241,8 +241,7 @@ HttpRequestHeaders::HeaderVector::iterator HttpRequestHeaders::FindHeader(const base::StringPiece& key) { for (HeaderVector::iterator it = headers_.begin(); it != headers_.end(); ++it) { - if (key.length() == it->key.length() && - !base::strncasecmp(key.data(), it->key.data(), key.length())) + if (base::EqualsCaseInsensitiveASCII(key, it->key)) return it; } @@ -253,8 +252,7 @@ HttpRequestHeaders::HeaderVector::const_iterator HttpRequestHeaders::FindHeader(const base::StringPiece& key) const { for (HeaderVector::const_iterator it = headers_.begin(); it != headers_.end(); ++it) { - if (key.length() == it->key.length() && - !base::strncasecmp(key.data(), it->key.data(), key.length())) + if (base::EqualsCaseInsensitiveASCII(key, it->key)) return it; } diff --git a/chromium/net/http/http_response_body_drainer.h b/chromium/net/http/http_response_body_drainer.h index a4255d0dea9..33368225be6 100644 --- a/chromium/net/http/http_response_body_drainer.h +++ b/chromium/net/http/http_response_body_drainer.h @@ -56,7 +56,7 @@ class NET_EXPORT_PRIVATE HttpResponseBodyDrainer { State next_state_; int total_read_; CompletionCallback user_callback_; - base::OneShotTimer<HttpResponseBodyDrainer> timer_; + base::OneShotTimer timer_; HttpNetworkSession* session_; DISALLOW_COPY_AND_ASSIGN(HttpResponseBodyDrainer); diff --git a/chromium/net/http/http_response_body_drainer_unittest.cc b/chromium/net/http/http_response_body_drainer_unittest.cc index ca206b7f5c7..e44e6ee1e8a 100644 --- a/chromium/net/http/http_response_body_drainer_unittest.cc +++ b/chromium/net/http/http_response_body_drainer_unittest.cc @@ -4,6 +4,8 @@ #include "net/http/http_response_body_drainer.h" +#include <stdint.h> + #include <cstring> #include "base/bind.h" @@ -96,13 +98,14 @@ class MockHttpStream : public HttpStream { return ERR_UNEXPECTED; } - bool CanFindEndOfResponse() const override { return true; } bool IsConnectionReused() const override { return false; } void SetConnectionReused() override {} - bool IsConnectionReusable() const override { return false; } - int64 GetTotalReceivedBytes() const override { return 0; } + bool CanReuseConnection() const override { return false; } + int64_t GetTotalReceivedBytes() const override { return 0; } + int64_t GetTotalSentBytes() const override { return 0; } void GetSSLInfo(SSLInfo* ssl_info) override {} void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {} + bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; } // Mocked API int ReadResponseBody(IOBuffer* buf, @@ -118,8 +121,6 @@ class MockHttpStream : public HttpStream { bool IsResponseBodyComplete() const override { return is_complete_; } - bool IsSpdyHttpStream() const override { return false; } - bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override { return false; } diff --git a/chromium/net/http/http_response_headers.cc b/chromium/net/http/http_response_headers.cc index 7c0c5ad2ee1..c535e0ab64e 100644 --- a/chromium/net/http/http_response_headers.cc +++ b/chromium/net/http/http_response_headers.cc @@ -95,15 +95,13 @@ const char* const kNonUpdatedHeaderPrefixes[] = { "x-webkit-" }; -bool ShouldUpdateHeader(const std::string::const_iterator& name_begin, - const std::string::const_iterator& name_end) { +bool ShouldUpdateHeader(base::StringPiece name) { for (size_t i = 0; i < arraysize(kNonUpdatedHeaders); ++i) { - if (base::LowerCaseEqualsASCII(name_begin, name_end, kNonUpdatedHeaders[i])) + if (base::LowerCaseEqualsASCII(name, kNonUpdatedHeaders[i])) return false; } for (size_t i = 0; i < arraysize(kNonUpdatedHeaderPrefixes); ++i) { - if (base::StartsWith(base::StringPiece(name_begin, name_end), - kNonUpdatedHeaderPrefixes[i], + if (base::StartsWith(name, kNonUpdatedHeaderPrefixes[i], base::CompareCase::INSENSITIVE_ASCII)) return false; } @@ -208,9 +206,8 @@ void HttpResponseHeaders::Persist(base::Pickle* pickle, while (++k < parsed_.size() && parsed_[k].is_continuation()) {} --k; - std::string header_name(parsed_[i].name_begin, parsed_[i].name_end); - base::StringToLowerASCII(&header_name); - + std::string header_name = base::ToLowerASCII( + base::StringPiece(parsed_[i].name_begin, parsed_[i].name_end)); if (filter_headers.find(header_name) == filter_headers.end()) { // Make sure there is a null after the value. blob.append(parsed_[i].name_begin, parsed_[k].value_end); @@ -248,16 +245,14 @@ void HttpResponseHeaders::Update(const HttpResponseHeaders& new_headers) { while (++k < new_parsed.size() && new_parsed[k].is_continuation()) {} --k; - const std::string::const_iterator& name_begin = new_parsed[i].name_begin; - const std::string::const_iterator& name_end = new_parsed[i].name_end; - if (ShouldUpdateHeader(name_begin, name_end)) { - std::string name(name_begin, name_end); - base::StringToLowerASCII(&name); - updated_headers.insert(name); + base::StringPiece name(new_parsed[i].name_begin, new_parsed[i].name_end); + if (ShouldUpdateHeader(name)) { + std::string name_lower = base::ToLowerASCII(name); + updated_headers.insert(name_lower); // Preserve this header line in the merged result, making sure there is // a null after the value. - new_raw_headers.append(name_begin, new_parsed[k].value_end); + new_raw_headers.append(new_parsed[i].name_begin, new_parsed[k].value_end); new_raw_headers.push_back('\0'); } @@ -279,8 +274,8 @@ void HttpResponseHeaders::MergeWithHeaders(const std::string& raw_headers, while (++k < parsed_.size() && parsed_[k].is_continuation()) {} --k; - std::string name(parsed_[i].name_begin, parsed_[i].name_end); - base::StringToLowerASCII(&name); + std::string name = base::ToLowerASCII( + base::StringPiece(parsed_[i].name_begin, parsed_[i].name_end)); if (headers_to_remove.find(name) == headers_to_remove.end()) { // It's ok to preserve this header in the final result. new_raw_headers.append(parsed_[i].name_begin, parsed_[k].value_end); @@ -302,8 +297,7 @@ void HttpResponseHeaders::RemoveHeader(const std::string& name) { std::string new_raw_headers(raw_headers_.c_str()); new_raw_headers.push_back('\0'); - std::string lowercase_name(name); - base::StringToLowerASCII(&lowercase_name); + std::string lowercase_name = base::ToLowerASCII(name); HeaderSet to_remove; to_remove.insert(lowercase_name); MergeWithHeaders(new_raw_headers, to_remove); @@ -311,8 +305,7 @@ void HttpResponseHeaders::RemoveHeader(const std::string& name) { void HttpResponseHeaders::RemoveHeaderLine(const std::string& name, const std::string& value) { - std::string name_lowercase(name); - base::StringToLowerASCII(&name_lowercase); + std::string name_lowercase = base::ToLowerASCII(name); std::string new_raw_headers(GetStatusLine()); new_raw_headers.push_back('\0'); @@ -323,9 +316,7 @@ void HttpResponseHeaders::RemoveHeaderLine(const std::string& name, std::string old_header_name; std::string old_header_value; while (EnumerateHeaderLines(&iter, &old_header_name, &old_header_value)) { - std::string old_header_name_lowercase(name); - base::StringToLowerASCII(&old_header_name_lowercase); - + std::string old_header_name_lowercase = base::ToLowerASCII(old_header_name); if (name_lowercase == old_header_name_lowercase && value == old_header_value) continue; @@ -475,7 +466,7 @@ void HttpResponseHeaders::GetNormalizedHeaders(std::string* output) const { DCHECK(!parsed_[i].is_continuation()); std::string name(parsed_[i].name_begin, parsed_[i].name_end); - std::string lower_name = base::StringToLowerASCII(name); + std::string lower_name = base::ToLowerASCII(name); iter = headers_map.find(lower_name); if (iter == headers_map.end()) { @@ -603,9 +594,7 @@ bool HttpResponseHeaders::HasHeaderValue(const base::StringPiece& name, void* iter = NULL; std::string temp; while (EnumerateHeader(&iter, name, &temp)) { - if (value.size() == temp.size() && - std::equal(temp.begin(), temp.end(), value.begin(), - base::CaseInsensitiveCompare<char>())) + if (base::EqualsCaseInsensitiveASCII(value, temp)) return true; } return false; @@ -633,7 +622,8 @@ HttpVersion HttpResponseHeaders::ParseVersion( // TODO: (1*DIGIT apparently means one or more digits, but we only handle 1). // TODO: handle leading zeros, which is allowed by the rfc1616 sec 3.1. - if ((line_end - p < 4) || !base::LowerCaseEqualsASCII(p, p + 4, "http")) { + if (!base::StartsWith(base::StringPiece(line_begin, line_end), "http", + base::CompareCase::INSENSITIVE_ASCII)) { DVLOG(1) << "missing status line"; return HttpVersion(); } @@ -743,11 +733,8 @@ size_t HttpResponseHeaders::FindHeader(size_t from, for (size_t i = from; i < parsed_.size(); ++i) { if (parsed_[i].is_continuation()) continue; - const std::string::const_iterator& name_begin = parsed_[i].name_begin; - const std::string::const_iterator& name_end = parsed_[i].name_end; - if (static_cast<size_t>(name_end - name_begin) == search.size() && - std::equal(name_begin, name_end, search.begin(), - base::CaseInsensitiveCompare<char>())) + base::StringPiece name(parsed_[i].name_begin, parsed_[i].name_end); + if (base::EqualsCaseInsensitiveASCII(search, name)) return i; } @@ -764,8 +751,8 @@ bool HttpResponseHeaders::GetCacheControlDirective(const StringPiece& directive, void* iter = NULL; while (EnumerateHeader(&iter, name, &value)) { if (value.size() > directive_size + 1 && - base::LowerCaseEqualsASCII( - value.begin(), value.begin() + directive_size, directive.begin()) && + base::StartsWith(value, directive, + base::CompareCase::INSENSITIVE_ASCII) && value[directive_size] == '=') { int64 seconds; base::StringToInt64( @@ -849,9 +836,8 @@ void HttpResponseHeaders::AddNonCacheableHeaders(HeaderSet* result) const { // assuming the header is not empty, lowercase and insert into set if (item_end > item) { - std::string name(&*item, item_end - item); - base::StringToLowerASCII(&name); - result->insert(name); + result->insert( + base::ToLowerASCII(base::StringPiece(&*item, item_end - item))); } // Continue to next item. @@ -1309,8 +1295,9 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position, std::string::const_iterator content_range_spec_end = content_range_spec.begin() + space_position; HttpUtil::TrimLWS(&content_range_spec_begin, &content_range_spec_end); - if (!base::LowerCaseEqualsASCII(content_range_spec_begin, - content_range_spec_end, "bytes")) { + if (!base::LowerCaseEqualsASCII( + base::StringPiece(content_range_spec_begin, content_range_spec_end), + "bytes")) { return false; } @@ -1373,8 +1360,9 @@ bool HttpResponseHeaders::GetContentRange(int64* first_byte_position, content_range_spec.end(); HttpUtil::TrimLWS(&instance_length_begin, &instance_length_end); - if (base::LowerCaseEqualsASCII(instance_length_begin, instance_length_end, - "*")) { + if (base::StartsWith( + base::StringPiece(instance_length_begin, instance_length_end), "*", + base::CompareCase::SENSITIVE)) { return false; } else if (!base::StringToInt64(StringPiece(instance_length_begin, instance_length_end), diff --git a/chromium/net/http/http_response_headers_unittest.cc b/chromium/net/http/http_response_headers_unittest.cc index 0184885dcd3..35a63608c05 100644 --- a/chromium/net/http/http_response_headers_unittest.cc +++ b/chromium/net/http/http_response_headers_unittest.cc @@ -467,8 +467,8 @@ const struct PersistData persistence_tests[] = { "Strict-Transport-Security: max-age=1576800\n" "Bar: 1\n" "Public-Key-Pins: max-age=100000; " - "pin-sha1=\"ObT42aoSpAqWdY9WfRfL7i0HsVk=\";" - "pin-sha1=\"7kW49EVwZG0hSNx41ZO/fUPN0ek=\"", + "pin-sha256=\"1111111111111111111111111111111111111111111=\";" + "pin-sha256=\"2222222222222222222222222222222222222222222=\"", "HTTP/1.1 200 OK\n" "Bar: 1\n"}, diff --git a/chromium/net/http/http_response_info.cc b/chromium/net/http/http_response_info.cc index dbfb62e11bb..fa9d63cccb4 100644 --- a/chromium/net/http/http_response_info.cc +++ b/chromium/net/http/http_response_info.cc @@ -93,6 +93,9 @@ enum { RESPONSE_INFO_UNUSED_SINCE_PREFETCH = 1 << 21, + // This bit is set if the response has a key-exchange-info field at the end. + RESPONSE_INFO_HAS_KEY_EXCHANGE_INFO = 1 << 22, + // TODO(darin): Add other bits to indicate alternate request methods. // For now, we don't support storing those. }; @@ -106,8 +109,8 @@ HttpResponseInfo::HttpResponseInfo() was_fetched_via_proxy(false), did_use_http_auth(false), unused_since_prefetch(false), - connection_info(CONNECTION_INFO_UNKNOWN) { -} + async_revalidation_required(false), + connection_info(CONNECTION_INFO_UNKNOWN) {} HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs) : was_cached(rhs.was_cached), @@ -119,6 +122,7 @@ HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs) proxy_server(rhs.proxy_server), did_use_http_auth(rhs.did_use_http_auth), unused_since_prefetch(rhs.unused_since_prefetch), + async_revalidation_required(rhs.async_revalidation_required), socket_address(rhs.socket_address), npn_negotiated_protocol(rhs.npn_negotiated_protocol), connection_info(rhs.connection_info), @@ -129,8 +133,7 @@ HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs) ssl_info(rhs.ssl_info), headers(rhs.headers), vary_data(rhs.vary_data), - metadata(rhs.metadata) { -} + metadata(rhs.metadata) {} HttpResponseInfo::~HttpResponseInfo() { } @@ -145,6 +148,7 @@ HttpResponseInfo& HttpResponseInfo::operator=(const HttpResponseInfo& rhs) { was_fetched_via_proxy = rhs.was_fetched_via_proxy; did_use_http_auth = rhs.did_use_http_auth; unused_since_prefetch = rhs.unused_since_prefetch; + async_revalidation_required = rhs.async_revalidation_required; socket_address = rhs.socket_address; npn_negotiated_protocol = rhs.npn_negotiated_protocol; connection_info = rhs.connection_info; @@ -272,6 +276,14 @@ bool HttpResponseInfo::InitFromPickle(const base::Pickle& pickle, } } + // Read key_exchange_info + if (flags & RESPONSE_INFO_HAS_KEY_EXCHANGE_INFO) { + int key_exchange_info; + if (!iter.ReadInt(&key_exchange_info)) + return false; + ssl_info.key_exchange_info = key_exchange_info; + } + was_fetched_via_spdy = (flags & RESPONSE_INFO_WAS_SPDY) != 0; was_npn_negotiated = (flags & RESPONSE_INFO_WAS_NPN) != 0; @@ -296,6 +308,8 @@ void HttpResponseInfo::Persist(base::Pickle* pickle, flags |= RESPONSE_INFO_HAS_CERT_STATUS; if (ssl_info.security_bits != -1) flags |= RESPONSE_INFO_HAS_SECURITY_BITS; + if (ssl_info.key_exchange_info != 0) + flags |= RESPONSE_INFO_HAS_KEY_EXCHANGE_INFO; if (ssl_info.connection_status != 0) flags |= RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS; } @@ -367,6 +381,9 @@ void HttpResponseInfo::Persist(base::Pickle* pickle, if (connection_info != CONNECTION_INFO_UNKNOWN) pickle->WriteInt(static_cast<int>(connection_info)); + + if (ssl_info.is_valid() && ssl_info.key_exchange_info != 0) + pickle->WriteInt(ssl_info.key_exchange_info); } HttpResponseInfo::ConnectionInfo HttpResponseInfo::ConnectionInfoFromNextProto( @@ -377,8 +394,6 @@ HttpResponseInfo::ConnectionInfo HttpResponseInfo::ConnectionInfoFromNextProto( case kProtoSPDY3: case kProtoSPDY31: return CONNECTION_INFO_SPDY3; - case kProtoHTTP2_14: - return CONNECTION_INFO_HTTP2_14; case kProtoHTTP2: return CONNECTION_INFO_HTTP2; case kProtoQUIC1SPDY3: @@ -405,15 +420,12 @@ std::string HttpResponseInfo::ConnectionInfoToString( return "spdy/2"; case CONNECTION_INFO_SPDY3: return "spdy/3"; + // Since ConnectionInfo is persisted to disk, deprecated values have to be + // handled. Note that h2-14 and h2-15 are essentially wire compatible with + // h2. + // Intentional fallthrough. case CONNECTION_INFO_HTTP2_14: - // For internal consistency, HTTP/2 is named SPDY4 within Chromium. - // This is the HTTP/2 draft-14 identifier. - return "h2-14"; case CONNECTION_INFO_HTTP2_15: - // Since ConnectionInfo is persisted to disk, this value has to be - // handled, but h2-15 is removed. Note that h2-14 and h2-15 are wire - // compatible for all practical purposes. - return "h2-14"; case CONNECTION_INFO_HTTP2: return "h2"; case CONNECTION_INFO_QUIC1_SPDY3: diff --git a/chromium/net/http/http_response_info.h b/chromium/net/http/http_response_info.h index 1ce64f82698..dd1b3da351e 100644 --- a/chromium/net/http/http_response_info.h +++ b/chromium/net/http/http_response_info.h @@ -106,6 +106,11 @@ class NET_EXPORT HttpResponseInfo { // used since. bool unused_since_prefetch; + // True if this resource is stale and requires async revalidation. + // This value is not persisted by Persist(); it is only ever set when the + // response is retrieved from the cache. + bool async_revalidation_required; + // Remote address of the socket which fetched this resource. // // NOTE: If the response was served from the cache (was_cached is true), diff --git a/chromium/net/http/http_response_info_unittest.cc b/chromium/net/http/http_response_info_unittest.cc index ef7d4118eac..d27fb1c8ff7 100644 --- a/chromium/net/http/http_response_info_unittest.cc +++ b/chromium/net/http/http_response_info_unittest.cc @@ -52,6 +52,30 @@ TEST_F(HttpResponseInfoTest, UnusedSincePrefetchPersistTrue) { EXPECT_TRUE(restored_response_info.unused_since_prefetch); } +TEST_F(HttpResponseInfoTest, AsyncRevalidationRequiredDefault) { + EXPECT_FALSE(response_info_.async_revalidation_required); +} + +TEST_F(HttpResponseInfoTest, AsyncRevalidationRequiredCopy) { + response_info_.async_revalidation_required = true; + net::HttpResponseInfo response_info_clone(response_info_); + EXPECT_TRUE(response_info_clone.async_revalidation_required); +} + +TEST_F(HttpResponseInfoTest, AsyncRevalidationRequiredAssign) { + response_info_.async_revalidation_required = true; + net::HttpResponseInfo response_info_clone; + response_info_clone = response_info_; + EXPECT_TRUE(response_info_clone.async_revalidation_required); +} + +TEST_F(HttpResponseInfoTest, AsyncRevalidationRequiredNotPersisted) { + response_info_.async_revalidation_required = true; + net::HttpResponseInfo restored_response_info; + PickleAndRestore(response_info_, &restored_response_info); + EXPECT_FALSE(restored_response_info.async_revalidation_required); +} + } // namespace } // namespace net diff --git a/chromium/net/http/http_security_headers.cc b/chromium/net/http/http_security_headers.cc index d95e5878d7c..b99b206c3f3 100644 --- a/chromium/net/http/http_security_headers.cc +++ b/chromium/net/http/http_security_headers.cc @@ -5,15 +5,19 @@ #include "base/base64.h" #include "base/basictypes.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" #include "net/http/http_security_headers.h" #include "net/http/http_util.h" +#include "url/gurl.h" namespace net { namespace { +enum MaxAgeParsing { REQUIRE_MAX_AGE, DO_NOT_REQUIRE_MAX_AGE }; + static_assert(kMaxHSTSAgeSecs <= kuint32max, "kMaxHSTSAgeSecs too large"); // MaxAgeToInt converts a string representation of a "whole number" of @@ -23,7 +27,10 @@ static_assert(kMaxHSTSAgeSecs <= kuint32max, "kMaxHSTSAgeSecs too large"); bool MaxAgeToInt(std::string::const_iterator begin, std::string::const_iterator end, uint32* result) { - const std::string s(begin, end); + const base::StringPiece s(begin, end); + if (s.empty()) + return false; + int64 i = 0; // Return false on any StringToInt64 parse errors *except* for @@ -92,42 +99,16 @@ bool IsPinListValid(const HashValueVector& pins, HashesIntersect(pins, from_cert_chain); } -std::string Strip(const std::string& source) { - if (source.empty()) - return source; - - std::string::const_iterator start = source.begin(); - std::string::const_iterator end = source.end(); - HttpUtil::TrimLWS(&start, &end); - return std::string(start, end); -} - -typedef std::pair<std::string, std::string> StringPair; - -StringPair Split(const std::string& source, char delimiter) { - StringPair pair; - size_t point = source.find(delimiter); - - pair.first = source.substr(0, point); - if (std::string::npos != point) - pair.second = source.substr(point + 1); - - return pair; -} - -bool ParseAndAppendPin(const std::string& value, +bool ParseAndAppendPin(std::string::const_iterator begin, + std::string::const_iterator end, HashValueTag tag, HashValueVector* hashes) { - // Pins are always quoted. - if (value.empty() || !HttpUtil::IsQuote(value[0])) + const base::StringPiece value(begin, end); + if (value.empty()) return false; - std::string unquoted = HttpUtil::Unquote(value); - if (unquoted.empty()) - return false; - std::string decoded; - if (!base::Base64Decode(unquoted, &decoded)) + if (!base::Base64Decode(value, &decoded)) return false; HashValue hash(tag); @@ -139,6 +120,79 @@ bool ParseAndAppendPin(const std::string& value, return true; } +bool ParseHPKPHeaderImpl(const std::string& value, + MaxAgeParsing max_age_status, + base::TimeDelta* max_age, + bool* include_subdomains, + HashValueVector* hashes, + GURL* report_uri) { + bool parsed_max_age = false; + bool include_subdomains_candidate = false; + uint32 max_age_candidate = 0; + GURL parsed_report_uri; + HashValueVector pins; + bool require_max_age = max_age_status == REQUIRE_MAX_AGE; + + HttpUtil::NameValuePairsIterator name_value_pairs( + value.begin(), value.end(), ';', + HttpUtil::NameValuePairsIterator::VALUES_OPTIONAL); + + while (name_value_pairs.GetNext()) { + if (base::LowerCaseEqualsASCII( + base::StringPiece(name_value_pairs.name_begin(), + name_value_pairs.name_end()), + "max-age")) { + if (!MaxAgeToInt(name_value_pairs.value_begin(), + name_value_pairs.value_end(), &max_age_candidate)) { + return false; + } + parsed_max_age = true; + } else if (base::LowerCaseEqualsASCII( + base::StringPiece(name_value_pairs.name_begin(), + name_value_pairs.name_end()), + "pin-sha256")) { + // Pins are always quoted. + if (!name_value_pairs.value_is_quoted() || + !ParseAndAppendPin(name_value_pairs.value_begin(), + name_value_pairs.value_end(), HASH_VALUE_SHA256, + &pins)) { + return false; + } + } else if (base::LowerCaseEqualsASCII( + base::StringPiece(name_value_pairs.name_begin(), + name_value_pairs.name_end()), + "includesubdomains")) { + include_subdomains_candidate = true; + } else if (base::LowerCaseEqualsASCII( + base::StringPiece(name_value_pairs.name_begin(), + name_value_pairs.name_end()), + "report-uri")) { + // report-uris are always quoted. + if (!name_value_pairs.value_is_quoted()) + return false; + + parsed_report_uri = GURL(name_value_pairs.value()); + if (parsed_report_uri.is_empty() || !parsed_report_uri.is_valid()) + return false; + } else { + // Silently ignore unknown directives for forward compatibility. + } + } + + if (!name_value_pairs.valid()) + return false; + + if (!parsed_max_age && require_max_age) + return false; + + *max_age = base::TimeDelta::FromSeconds(max_age_candidate); + *include_subdomains = include_subdomains_candidate; + hashes->swap(pins); + *report_uri = parsed_report_uri; + + return true; +} + } // namespace // Parse the Strict-Transport-Security header, as currently defined in @@ -276,59 +330,48 @@ bool ParseHSTSHeader(const std::string& value, // "Public-Key-Pins" ":" // "max-age" "=" delta-seconds ";" // "pin-" algo "=" base64 [ ";" ... ] +// [ ";" "includeSubdomains" ] +// [ ";" "report-uri" "=" uri-reference ] bool ParseHPKPHeader(const std::string& value, const HashValueVector& chain_hashes, base::TimeDelta* max_age, bool* include_subdomains, - HashValueVector* hashes) { - bool parsed_max_age = false; - bool include_subdomains_candidate = false; - uint32 max_age_candidate = 0; - HashValueVector pins; - - std::string source = value; - - while (!source.empty()) { - StringPair semicolon = Split(source, ';'); - semicolon.first = Strip(semicolon.first); - semicolon.second = Strip(semicolon.second); - StringPair equals = Split(semicolon.first, '='); - equals.first = Strip(equals.first); - equals.second = Strip(equals.second); - - if (base::LowerCaseEqualsASCII(equals.first, "max-age")) { - if (equals.second.empty() || - !MaxAgeToInt(equals.second.begin(), equals.second.end(), - &max_age_candidate)) { - return false; - } - parsed_max_age = true; - } else if (base::LowerCaseEqualsASCII(equals.first, "pin-sha1")) { - if (!ParseAndAppendPin(equals.second, HASH_VALUE_SHA1, &pins)) - return false; - } else if (base::LowerCaseEqualsASCII(equals.first, "pin-sha256")) { - if (!ParseAndAppendPin(equals.second, HASH_VALUE_SHA256, &pins)) - return false; - } else if (base::LowerCaseEqualsASCII(equals.first, "includesubdomains")) { - include_subdomains_candidate = true; - } else { - // Silently ignore unknown directives for forward compatibility. - } - - source = semicolon.second; - } - - if (!parsed_max_age) + HashValueVector* hashes, + GURL* report_uri) { + base::TimeDelta candidate_max_age; + bool candidate_include_subdomains; + HashValueVector candidate_hashes; + GURL candidate_report_uri; + + if (!ParseHPKPHeaderImpl(value, REQUIRE_MAX_AGE, &candidate_max_age, + &candidate_include_subdomains, &candidate_hashes, + &candidate_report_uri)) { return false; + } - if (!IsPinListValid(pins, chain_hashes)) + if (!IsPinListValid(candidate_hashes, chain_hashes)) return false; - *max_age = base::TimeDelta::FromSeconds(max_age_candidate); - *include_subdomains = include_subdomains_candidate; - hashes->swap(pins); - + *max_age = candidate_max_age; + *include_subdomains = candidate_include_subdomains; + hashes->swap(candidate_hashes); + *report_uri = candidate_report_uri; return true; } +// "Public-Key-Pins-Report-Only" ":" +// [ "max-age" "=" delta-seconds ";" ] +// "pin-" algo "=" base64 [ ";" ... ] +// [ ";" "includeSubdomains" ] +// [ ";" "report-uri" "=" uri-reference ] +bool ParseHPKPReportOnlyHeader(const std::string& value, + bool* include_subdomains, + HashValueVector* hashes, + GURL* report_uri) { + // max-age is irrelevant for Report-Only headers. + base::TimeDelta unused_max_age; + return ParseHPKPHeaderImpl(value, DO_NOT_REQUIRE_MAX_AGE, &unused_max_age, + include_subdomains, hashes, report_uri); +} + } // namespace net diff --git a/chromium/net/http/http_security_headers.h b/chromium/net/http/http_security_headers.h index 12e6be9000a..f54df691fae 100644 --- a/chromium/net/http/http_security_headers.h +++ b/chromium/net/http/http_security_headers.h @@ -8,12 +8,13 @@ #include <string> #include "base/basictypes.h" -#include "base/gtest_prod_util.h" #include "base/time/time.h" #include "base/values.h" #include "net/base/hash_value.h" #include "net/base/net_export.h" +class GURL; + namespace net { const int64 kMaxHSTSAgeSecs = 86400 * 365; // 1 year @@ -31,9 +32,9 @@ bool NET_EXPORT_PRIVATE ParseHSTSHeader(const std::string& value, bool* include_subdomains); // Parses |value| as a Public-Key-Pins header value. If successful, returns -// true and populates the |*max_age|, |*include_subdomains|, and |*hashes| -// values. Otherwise returns false and leaves the output parameters -// unchanged. +// true and populates the |*max_age|, |*include_subdomains|, |*hashes|, and +// |*report_uri| values. Otherwise returns false and leaves the output +// parameters unchanged. // // value is the right-hand side of: // @@ -41,6 +42,7 @@ bool NET_EXPORT_PRIVATE ParseHSTSHeader(const std::string& value, // "max-age" "=" delta-seconds ";" // "pin-" algo "=" base64 [ ";" ... ] // [ ";" "includeSubdomains" ] +// [ ";" "report-uri" "=" uri-reference ] // // For this function to return true, the key hashes specified by the HPKP // header must pass two additional checks. There MUST be at least one key @@ -52,8 +54,26 @@ bool NET_EXPORT_PRIVATE ParseHPKPHeader(const std::string& value, const HashValueVector& chain_hashes, base::TimeDelta* max_age, bool* include_subdomains, - HashValueVector* hashes); + HashValueVector* hashes, + GURL* report_uri); +// Parses |value| as a Public-Key-Pins-Report-Only header value. If +// successful, returns true and populates the |*include_subdomains|, +// |*hashes|, and |*report_uri| values. Otherwise returns false and +// leaves the output parameters unchanged. +// +// value is the right-hand side of: +// +// "Public-Key-Pins-Report-Only" ":" +// [ "max-age" "=" delta-seconds ";" ] +// "pin-" algo "=" base64 [ ";" ... ] +// [ ";" "includeSubdomains" ] +// [ ";" "report-uri" "=" uri-reference ] +// +bool NET_EXPORT_PRIVATE ParseHPKPReportOnlyHeader(const std::string& value, + bool* include_subdomains, + HashValueVector* hashes, + GURL* report_uri); } // namespace net #endif // NET_HTTP_HTTP_SECURITY_HEADERS_H_ diff --git a/chromium/net/http/http_security_headers_unittest.cc b/chromium/net/http/http_security_headers_unittest.cc index 0dd3020481e..4a510f2f11d 100644 --- a/chromium/net/http/http_security_headers_unittest.cc +++ b/chromium/net/http/http_security_headers_unittest.cc @@ -6,9 +6,9 @@ #include <algorithm> #include "base/base64.h" -#include "base/sha1.h" #include "base/strings/string_piece.h" #include "crypto/sha2.h" +#include "net/base/host_port_pair.h" #include "net/base/test_completion_callback.h" #include "net/http/http_security_headers.h" #include "net/http/http_util.h" @@ -35,9 +35,6 @@ std::string GetTestPinImpl(uint8 label, HashValueTag tag, bool quoted) { std::string ret; switch (hash_value.tag) { - case HASH_VALUE_SHA1: - ret = "pin-sha1="; - break; case HASH_VALUE_SHA256: ret = "pin-sha256="; break; @@ -63,6 +60,39 @@ std::string GetTestPinUnquoted(uint8 label, HashValueTag tag) { }; +// Parses the given header |value| as both a Public-Key-Pins-Report-Only +// and Public-Key-Pins header. Returns true if the value parses +// successfully for both header types, and if the parsed hashes and +// report_uri match for both header types. +bool ParseAsHPKPHeader(const std::string& value, + const HashValueVector& chain_hashes, + base::TimeDelta* max_age, + bool* include_subdomains, + HashValueVector* hashes, + GURL* report_uri) { + GURL report_only_uri; + bool report_only_include_subdomains; + HashValueVector report_only_hashes; + if (!ParseHPKPReportOnlyHeader(value, &report_only_include_subdomains, + &report_only_hashes, &report_only_uri)) { + return false; + } + + bool result = ParseHPKPHeader(value, chain_hashes, max_age, + include_subdomains, hashes, report_uri); + if (!result || report_only_include_subdomains != *include_subdomains || + report_only_uri != *report_uri || + report_only_hashes.size() != hashes->size()) { + return false; + } + + for (size_t i = 0; i < report_only_hashes.size(); i++) { + if (!(*hashes)[i].Equals(report_only_hashes[i])) + return false; + } + + return true; +} class HttpSecurityHeadersTest : public testing::Test { }; @@ -152,6 +182,7 @@ static void TestBogusPinsHeaders(HashValueTag tag) { bool include_subdomains; HashValueVector hashes; HashValueVector chain_hashes; + GURL report_uri; // Set some fake "chain" hashes chain_hashes.push_back(GetTestHashValue(1, tag)); @@ -163,78 +194,105 @@ static void TestBogusPinsHeaders(HashValueTag tag) { std::string good_pin_unquoted = GetTestPinUnquoted(2, tag); std::string backup_pin = GetTestPin(4, tag); - EXPECT_FALSE(ParseHPKPHeader(std::string(), chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" ", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader("abc", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" abc", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" abc ", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-age", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" max-age", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" max-age ", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-age=", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" max-age=", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" max-age =", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" max-age= ", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" max-age = ", chain_hashes, - &max_age, &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" max-age = xy", chain_hashes, - &max_age, &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader(" max-age = 3488a923", - chain_hashes, &max_age, &include_subdomains, - &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-age=3488a923 ", chain_hashes, - &max_age, &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-ag=3488923pins=" + good_pin + "," + - backup_pin, - chain_hashes, &max_age, &include_subdomains, - &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923" + backup_pin, - chain_hashes, &max_age, &include_subdomains, - &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + backup_pin, - chain_hashes, &max_age, &include_subdomains, - &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + backup_pin + ";" + - backup_pin, - chain_hashes, &max_age, &include_subdomains, - &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + good_pin + ";" + - good_pin, - chain_hashes, &max_age, &include_subdomains, - &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-aged=3488923; " + good_pin, - chain_hashes, &max_age, &include_subdomains, - &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-age==3488923", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader("amax-age=3488923", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-age=-3488923", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-age=3488923;", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-age=3488923 e", chain_hashes, - &max_age, &include_subdomains, &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-age=3488923 includesubdomain", - chain_hashes, &max_age, &include_subdomains, - &hashes)); - EXPECT_FALSE(ParseHPKPHeader("max-age=34889.23", chain_hashes, &max_age, - &include_subdomains, &hashes)); - EXPECT_FALSE( - ParseHPKPHeader("max-age=243; " + good_pin_unquoted + ";" + backup_pin, - chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_FALSE(ParseAsHPKPHeader(std::string(), chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" ", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("abc", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" abc", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" abc ", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-age", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" max-age", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" max-age ", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-age=", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" max-age=", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" max-age =", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" max-age= ", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" max-age = ", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" max-age = xy", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader(" max-age = 3488a923", chain_hashes, + &max_age, &include_subdomains, &hashes, + &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488a923 ", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader( + "max-ag=3488923pins=" + good_pin + "," + backup_pin, chain_hashes, + &max_age, &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader( + "max-age=3488923;pins=" + good_pin + "," + backup_pin + + "report-uri=\"http://foo.com\"", + chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-aged=3488923" + backup_pin, chain_hashes, + &max_age, &include_subdomains, &hashes, + &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-aged=3488923; " + backup_pin, + chain_hashes, &max_age, &include_subdomains, + &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader( + "max-aged=3488923; " + backup_pin + ";" + backup_pin, chain_hashes, + &max_age, &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader( + "max-aged=3488923; " + good_pin + ";" + good_pin, chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-aged=3488923; " + good_pin, chain_hashes, + &max_age, &include_subdomains, &hashes, + &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-age==3488923", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("amax-age=3488923", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-age=-3488923", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488923;", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488923 e", chain_hashes, + &max_age, &include_subdomains, &hashes, + &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-age=3488923 includesubdomain", + chain_hashes, &max_age, &include_subdomains, + &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader( + "max-age=3488923 report-uri=\"http://foo.com\"", chain_hashes, + &max_age, &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-age=34889.23", chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader( + "max-age=243; " + good_pin_unquoted + ";" + backup_pin, chain_hashes, + &max_age, &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader( + "max-age=243; " + good_pin + ";" + backup_pin + ";report-uri=;", + chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader("max-age=243; " + good_pin + ";" + backup_pin + + ";report-uri=http://foo.com;", + chain_hashes, &max_age, &include_subdomains, + &hashes, &report_uri)); + EXPECT_FALSE(ParseAsHPKPHeader( + "max-age=243; " + good_pin + ";" + backup_pin + ";report-uri=''", + chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri)); + + // Test that the parser rejects misquoted strings. + EXPECT_FALSE(ParseAsHPKPHeader( + "max-age=999; " + backup_pin + "; " + good_pin + + "; report-uri=\"http://foo;bar\'", + chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri)); + + // Test that the parser rejects invalid report-uris. + EXPECT_FALSE(ParseAsHPKPHeader("max-age=999; " + backup_pin + "; " + + good_pin + "; report-uri=\"foo;bar\'", + chain_hashes, &max_age, &include_subdomains, + &hashes, &report_uri)); // Check the out args were not updated by checking the default // values for its predictable fields. @@ -405,6 +463,8 @@ static void TestValidPKPHeaders(HashValueTag tag) { bool include_subdomains; HashValueVector hashes; HashValueVector chain_hashes; + GURL expect_report_uri; + GURL report_uri; // Set some fake "chain" hashes into chain_hashes chain_hashes.push_back(GetTestHashValue(1, tag)); @@ -416,106 +476,175 @@ static void TestValidPKPHeaders(HashValueTag tag) { std::string good_pin2 = GetTestPin(3, tag); std::string backup_pin = GetTestPin(4, tag); - EXPECT_TRUE(ParseHPKPHeader( - "max-age=243; " + good_pin + ";" + backup_pin, - chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_TRUE(ParseAsHPKPHeader("max-age=243; " + good_pin + ";" + backup_pin, + chain_hashes, &max_age, &include_subdomains, + &hashes, &report_uri)); expect_max_age = base::TimeDelta::FromSeconds(243); EXPECT_EQ(expect_max_age, max_age); EXPECT_FALSE(include_subdomains); + EXPECT_TRUE(report_uri.is_empty()); - EXPECT_TRUE(ParseHPKPHeader( - " " + good_pin + "; " + backup_pin + " ; Max-agE = 567", - chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_TRUE(ParseAsHPKPHeader("max-age=243; " + good_pin + ";" + backup_pin + + "; report-uri= \"http://example.test/foo\"", + chain_hashes, &max_age, &include_subdomains, + &hashes, &report_uri)); + expect_max_age = base::TimeDelta::FromSeconds(243); + expect_report_uri = GURL("http://example.test/foo"); + EXPECT_EQ(expect_max_age, max_age); + EXPECT_FALSE(include_subdomains); + EXPECT_EQ(expect_report_uri, report_uri); + + EXPECT_TRUE(ParseAsHPKPHeader( + " " + good_pin + "; " + backup_pin + + " ; Max-agE = 567; repOrT-URi = \"http://example.test/foo\"", + chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri)); expect_max_age = base::TimeDelta::FromSeconds(567); + expect_report_uri = GURL("http://example.test/foo"); EXPECT_EQ(expect_max_age, max_age); EXPECT_FALSE(include_subdomains); + EXPECT_EQ(expect_report_uri, report_uri); - EXPECT_TRUE(ParseHPKPHeader( - "includeSubDOMAINS;" + good_pin + ";" + backup_pin + - " ; mAx-aGe = 890 ", - chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_TRUE(ParseAsHPKPHeader("includeSubDOMAINS;" + good_pin + ";" + + backup_pin + " ; mAx-aGe = 890 ", + chain_hashes, &max_age, &include_subdomains, + &hashes, &report_uri)); expect_max_age = base::TimeDelta::FromSeconds(890); EXPECT_EQ(expect_max_age, max_age); EXPECT_TRUE(include_subdomains); - EXPECT_TRUE(ParseHPKPHeader( - good_pin + ";" + backup_pin + "; max-age=123;IGNORED;", - chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_TRUE(ParseAsHPKPHeader( + good_pin + ";" + backup_pin + "; max-age=123;IGNORED;", chain_hashes, + &max_age, &include_subdomains, &hashes, &report_uri)); expect_max_age = base::TimeDelta::FromSeconds(123); EXPECT_EQ(expect_max_age, max_age); EXPECT_FALSE(include_subdomains); - EXPECT_TRUE(ParseHPKPHeader( - "max-age=394082;" + backup_pin + ";" + good_pin + "; ", - chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_TRUE(ParseAsHPKPHeader( + "max-age=394082;" + backup_pin + ";" + good_pin + "; ", chain_hashes, + &max_age, &include_subdomains, &hashes, &report_uri)); expect_max_age = base::TimeDelta::FromSeconds(394082); EXPECT_EQ(expect_max_age, max_age); EXPECT_FALSE(include_subdomains); - EXPECT_TRUE(ParseHPKPHeader( - "max-age=39408299 ;" + backup_pin + ";" + good_pin + "; ", - chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_TRUE(ParseAsHPKPHeader( + "max-age=39408299 ;" + backup_pin + ";" + good_pin + "; ", chain_hashes, + &max_age, &include_subdomains, &hashes, &report_uri)); expect_max_age = base::TimeDelta::FromSeconds( std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(39408299)))); EXPECT_EQ(expect_max_age, max_age); EXPECT_FALSE(include_subdomains); - EXPECT_TRUE(ParseHPKPHeader( + EXPECT_TRUE(ParseAsHPKPHeader( "max-age=39408038 ; cybers=39408038 ; includeSubdomains; " + good_pin + ";" + backup_pin + "; ", - chain_hashes, &max_age, &include_subdomains, &hashes)); + chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri)); expect_max_age = base::TimeDelta::FromSeconds( std::min(kMaxHSTSAgeSecs, static_cast<int64>(INT64_C(394082038)))); EXPECT_EQ(expect_max_age, max_age); EXPECT_TRUE(include_subdomains); - EXPECT_TRUE(ParseHPKPHeader( - " max-age=0 ; " + good_pin + ";" + backup_pin, - chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_TRUE(ParseAsHPKPHeader( + " max-age=0 ; " + good_pin + ";" + backup_pin, chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); expect_max_age = base::TimeDelta::FromSeconds(0); EXPECT_EQ(expect_max_age, max_age); EXPECT_FALSE(include_subdomains); - EXPECT_TRUE(ParseHPKPHeader( + EXPECT_TRUE(ParseAsHPKPHeader( " max-age=0 ; includeSubdomains; " + good_pin + ";" + backup_pin, - chain_hashes, &max_age, &include_subdomains, &hashes)); + chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri)); expect_max_age = base::TimeDelta::FromSeconds(0); EXPECT_EQ(expect_max_age, max_age); EXPECT_TRUE(include_subdomains); - EXPECT_TRUE(ParseHPKPHeader( + EXPECT_TRUE(ParseAsHPKPHeader( " max-age=999999999999999999999999999999999999999999999 ; " + backup_pin + ";" + good_pin + "; ", - chain_hashes, &max_age, &include_subdomains, &hashes)); + chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri)); + expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs); + EXPECT_EQ(expect_max_age, max_age); + EXPECT_FALSE(include_subdomains); + + EXPECT_TRUE(ParseAsHPKPHeader( + " max-age=999999999999999999999999999999999999999999999 ; " + + backup_pin + ";" + good_pin + + "; report-uri=\"http://example.test/foo\"", + chain_hashes, &max_age, &include_subdomains, &hashes, &report_uri)); expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs); + expect_report_uri = GURL("http://example.test/foo"); EXPECT_EQ(expect_max_age, max_age); EXPECT_FALSE(include_subdomains); + EXPECT_EQ(expect_report_uri, report_uri); // Test that parsing a different header resets the hashes. hashes.clear(); - EXPECT_TRUE(ParseHPKPHeader( - " max-age=999; " + - backup_pin + ";" + good_pin + "; ", - chain_hashes, &max_age, &include_subdomains, &hashes)); + EXPECT_TRUE(ParseAsHPKPHeader( + " max-age=999; " + backup_pin + ";" + good_pin + "; ", chain_hashes, + &max_age, &include_subdomains, &hashes, &report_uri)); EXPECT_EQ(2u, hashes.size()); - EXPECT_TRUE(ParseHPKPHeader( + EXPECT_TRUE(ParseAsHPKPHeader( " max-age=999; " + backup_pin + ";" + good_pin2 + "; ", chain_hashes, - &max_age, &include_subdomains, &hashes)); + &max_age, &include_subdomains, &hashes, &report_uri)); EXPECT_EQ(2u, hashes.size()); -} -TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA1) { - TestBogusPinsHeaders(HASH_VALUE_SHA1); + // Test that the parser correctly parses an unencoded ';' inside a + // quoted report-uri. + EXPECT_TRUE(ParseAsHPKPHeader("max-age=999; " + backup_pin + "; " + good_pin + + "; report-uri=\"http://foo.com/?;bar\"", + chain_hashes, &max_age, &include_subdomains, + &hashes, &report_uri)); + expect_max_age = base::TimeDelta::FromSeconds(999); + expect_report_uri = GURL("http://foo.com/?;bar"); + EXPECT_EQ(expect_max_age, max_age); + EXPECT_FALSE(include_subdomains); + EXPECT_EQ(expect_report_uri, report_uri); + + // Test that the parser correctly parses a report-uri with a >0x7f + // character. + std::string uri = "http://foo.com/"; + uri += char(0x7f); + expect_report_uri = GURL(uri); + EXPECT_TRUE(ParseAsHPKPHeader("max-age=999; " + backup_pin + "; " + good_pin + + "; report-uri=\"" + uri + "\"", + chain_hashes, &max_age, &include_subdomains, + &hashes, &report_uri)); + expect_max_age = base::TimeDelta::FromSeconds(999); + EXPECT_EQ(expect_max_age, max_age); + EXPECT_FALSE(include_subdomains); + EXPECT_EQ(expect_report_uri, report_uri); + + // Test that the parser allows quoted max-age values. + EXPECT_TRUE(ParseAsHPKPHeader( + "max-age='999'; " + backup_pin + "; " + good_pin, chain_hashes, &max_age, + &include_subdomains, &hashes, &report_uri)); + expect_max_age = base::TimeDelta::FromSeconds(999); + EXPECT_EQ(expect_max_age, max_age); + EXPECT_FALSE(include_subdomains); + + // Test that the parser handles escaped values. + expect_report_uri = GURL("http://foo.com'a"); + EXPECT_TRUE(ParseAsHPKPHeader("max-age=999; " + backup_pin + "; " + good_pin + + "; report-uri='http://foo.com\\'\\a'", + chain_hashes, &max_age, &include_subdomains, + &hashes, &report_uri)); + expect_max_age = base::TimeDelta::FromSeconds(999); + EXPECT_EQ(expect_max_age, max_age); + EXPECT_FALSE(include_subdomains); + EXPECT_EQ(expect_report_uri, report_uri); + + // Test that the parser does not require max-age for Report-Only + // headers. + expect_report_uri = GURL("http://foo.com"); + EXPECT_TRUE(ParseHPKPReportOnlyHeader( + backup_pin + "; " + good_pin + "; report-uri='http://foo.com'", + &include_subdomains, &hashes, &report_uri)); + EXPECT_EQ(expect_report_uri, report_uri); } TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA256) { TestBogusPinsHeaders(HASH_VALUE_SHA256); } -TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA1) { - TestValidPKPHeaders(HASH_VALUE_SHA1); -} - TEST_F(HttpSecurityHeadersTest, ValidPKPHeadersSHA256) { TestValidPKPHeaders(HASH_VALUE_SHA256); } @@ -534,11 +663,13 @@ TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) { HashValueVector saved_hashes = static_pkp_state.spki_hashes; // Add a header, which should only update the dynamic state. - HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); - HashValue backup_hash = GetTestHashValue(2, HASH_VALUE_SHA1); - std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); - std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); - std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; + HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256); + HashValue backup_hash = GetTestHashValue(2, HASH_VALUE_SHA256); + std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256); + std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA256); + GURL report_uri("http://google.com"); + std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin + + ";report-uri=\"" + report_uri.spec() + "\""; // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. SSLInfo ssl_info; @@ -560,6 +691,7 @@ TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) { TransportSecurityState::PKPState dynamic_pkp_state; EXPECT_TRUE(state.GetDynamicPKPState(domain, &dynamic_pkp_state)); EXPECT_EQ(2UL, dynamic_pkp_state.spki_hashes.size()); + EXPECT_EQ(report_uri, dynamic_pkp_state.report_uri); HashValueVector::const_iterator hash = std::find_if( dynamic_pkp_state.spki_hashes.begin(), @@ -577,12 +709,15 @@ TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPOnly) { hashes.push_back(good_hash); std::string failure_log; const bool is_issued_by_known_root = true; + HostPortPair domain_port(domain, 443); EXPECT_TRUE(state.CheckPublicKeyPins( - domain, is_issued_by_known_root, hashes, &failure_log)); + domain_port, is_issued_by_known_root, hashes, nullptr, nullptr, + TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); TransportSecurityState::PKPState new_dynamic_pkp_state; EXPECT_TRUE(state.GetDynamicPKPState(domain, &new_dynamic_pkp_state)); EXPECT_EQ(2UL, new_dynamic_pkp_state.spki_hashes.size()); + EXPECT_EQ(report_uri, new_dynamic_pkp_state.report_uri); hash = std::find_if(new_dynamic_pkp_state.spki_hashes.begin(), new_dynamic_pkp_state.spki_hashes.end(), @@ -609,9 +744,9 @@ TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPMaxAge0) { HashValueVector saved_hashes = static_pkp_state.spki_hashes; // Add a header, which should only update the dynamic state. - HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); - std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); - std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); + HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256); + std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256); + std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA256); std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. @@ -669,9 +804,11 @@ TEST_F(HttpSecurityHeadersTest, UpdateDynamicPKPMaxAge0) { new_static_pkp_state2.spki_hashes[2].data()[0] ^= 0x80; const bool is_issued_by_known_root = true; - EXPECT_FALSE(state.CheckPublicKeyPins(domain, is_issued_by_known_root, - new_static_pkp_state2.spki_hashes, - &failure_log)); + HostPortPair domain_port(domain, 443); + EXPECT_FALSE(state.CheckPublicKeyPins( + domain_port, is_issued_by_known_root, new_static_pkp_state2.spki_hashes, + nullptr, nullptr, TransportSecurityState::DISABLE_PIN_REPORTS, + &failure_log)); EXPECT_NE(0UL, failure_log.length()); } @@ -703,15 +840,15 @@ TEST_F(HttpSecurityHeadersTest, NoClobberPins) { EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); std::string failure_log; const bool is_issued_by_known_root = true; - EXPECT_TRUE(state.CheckPublicKeyPins(domain, - is_issued_by_known_root, - saved_hashes, - &failure_log)); + HostPortPair domain_port(domain, 443); + EXPECT_TRUE(state.CheckPublicKeyPins( + domain_port, is_issued_by_known_root, saved_hashes, nullptr, nullptr, + TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); // Add an HPKP header, which should only update the dynamic state. - HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA1); - std::string good_pin = GetTestPin(1, HASH_VALUE_SHA1); - std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA1); + HashValue good_hash = GetTestHashValue(1, HASH_VALUE_SHA256); + std::string good_pin = GetTestPin(1, HASH_VALUE_SHA256); + std::string backup_pin = GetTestPin(2, HASH_VALUE_SHA256); std::string header = "max-age = 10000; " + good_pin + "; " + backup_pin; // Construct a fake SSLInfo that will pass AddHPKPHeader's checks. @@ -726,10 +863,9 @@ TEST_F(HttpSecurityHeadersTest, NoClobberPins) { EXPECT_TRUE(state.ShouldUpgradeToSSL(domain)); // The dynamic pins, which do not match |saved_hashes|, should take // precedence over the static pins and cause the check to fail. - EXPECT_FALSE(state.CheckPublicKeyPins(domain, - is_issued_by_known_root, - saved_hashes, - &failure_log)); + EXPECT_FALSE(state.CheckPublicKeyPins( + domain_port, is_issued_by_known_root, saved_hashes, nullptr, nullptr, + TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); } // Tests that seeing an invalid HPKP header leaves the existing one alone. @@ -753,9 +889,10 @@ TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) { EXPECT_TRUE(state.HasPublicKeyPins("example.com")); std::string failure_log; bool is_issued_by_known_root = true; - EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root, - ssl_info.public_key_hashes, - &failure_log)); + HostPortPair domain_port("example.com", 443); + EXPECT_TRUE(state.CheckPublicKeyPins( + domain_port, is_issued_by_known_root, ssl_info.public_key_hashes, nullptr, + nullptr, TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); // Now assert an invalid one. This should fail. EXPECT_FALSE(state.AddHPKPHeader( @@ -764,9 +901,9 @@ TEST_F(HttpSecurityHeadersTest, IgnoreInvalidHeaders) { // The old pins must still exist. EXPECT_TRUE(state.HasPublicKeyPins("example.com")); - EXPECT_TRUE(state.CheckPublicKeyPins("example.com", is_issued_by_known_root, - ssl_info.public_key_hashes, - &failure_log)); + EXPECT_TRUE(state.CheckPublicKeyPins( + domain_port, is_issued_by_known_root, ssl_info.public_key_hashes, nullptr, + nullptr, TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); } }; // namespace net diff --git a/chromium/net/http/http_server_properties.cc b/chromium/net/http/http_server_properties.cc index 8d4ef947317..1e3ccd234f0 100644 --- a/chromium/net/http/http_server_properties.cc +++ b/chromium/net/http/http_server_properties.cc @@ -13,6 +13,7 @@ namespace net { const char kAlternateProtocolHeader[] = "Alternate-Protocol"; +const char kAlternativeServiceHeader[] = "Alt-Svc"; namespace { @@ -22,7 +23,6 @@ const char* const kAlternateProtocolStrings[] = { "npn-spdy/2", "npn-spdy/3", "npn-spdy/3.1", - "npn-h2-14", // HTTP/2 draft-14. Called SPDY4 internally. "npn-h2", "quic"}; @@ -53,7 +53,6 @@ const char* AlternateProtocolToString(AlternateProtocol protocol) { case DEPRECATED_NPN_SPDY_2: case NPN_SPDY_3: case NPN_SPDY_3_1: - case NPN_HTTP_2_14: case NPN_HTTP_2: case QUIC: DCHECK(IsAlternateProtocolValid(protocol)); @@ -84,8 +83,6 @@ AlternateProtocol AlternateProtocolFromNextProto(NextProto next_proto) { return NPN_SPDY_3; case kProtoSPDY31: return NPN_SPDY_3_1; - case kProtoHTTP2_14: - return NPN_HTTP_2_14; case kProtoHTTP2: return NPN_HTTP_2; case kProtoQUIC1SPDY3: diff --git a/chromium/net/http/http_server_properties.h b/chromium/net/http/http_server_properties.h index 780dd005e67..2e50f5ede71 100644 --- a/chromium/net/http/http_server_properties.h +++ b/chromium/net/http/http_server_properties.h @@ -67,7 +67,6 @@ enum AlternateProtocol { NPN_SPDY_MINIMUM_VERSION = DEPRECATED_NPN_SPDY_2, NPN_SPDY_3, NPN_SPDY_3_1, - NPN_HTTP_2_14, // HTTP/2 draft-14 NPN_HTTP_2, // HTTP/2 NPN_SPDY_MAXIMUM_VERSION = NPN_HTTP_2, QUIC, @@ -143,14 +142,20 @@ struct NET_EXPORT AlternativeServiceInfo { AlternativeServiceInfo() : alternative_service(), probability(0.0) {} AlternativeServiceInfo(const AlternativeService& alternative_service, - double probability) - : alternative_service(alternative_service), probability(probability) {} + double probability, + base::Time expiration) + : alternative_service(alternative_service), + probability(probability), + expiration(expiration) {} AlternativeServiceInfo(AlternateProtocol protocol, const std::string& host, uint16 port, - double probability) - : alternative_service(protocol, host, port), probability(probability) {} + double probability, + base::Time expiration) + : alternative_service(protocol, host, port), + probability(probability), + expiration(expiration) {} AlternativeServiceInfo( const AlternativeServiceInfo& alternative_service_info) = default; @@ -159,7 +164,7 @@ struct NET_EXPORT AlternativeServiceInfo { bool operator==(const AlternativeServiceInfo& other) const { return alternative_service == other.alternative_service && - probability == other.probability; + probability == other.probability && expiration == other.expiration; } bool operator!=(const AlternativeServiceInfo& other) const { @@ -170,6 +175,7 @@ struct NET_EXPORT AlternativeServiceInfo { AlternativeService alternative_service; double probability; + base::Time expiration; }; struct NET_EXPORT SupportsQuic { @@ -209,6 +215,7 @@ typedef base::MRUCache<HostPortPair, SettingsMap> SpdySettingsMap; typedef base::MRUCache<HostPortPair, ServerNetworkStats> ServerNetworkStatsMap; extern const char kAlternateProtocolHeader[]; +extern const char kAlternativeServiceHeader[]; // The interface for setting/retrieving the HTTP server properties. // Currently, this class manages servers': @@ -264,7 +271,8 @@ class NET_EXPORT HttpServerProperties { virtual bool SetAlternativeService( const HostPortPair& origin, const AlternativeService& alternative_service, - double alternative_probability) = 0; + double alternative_probability, + base::Time expiration) = 0; // Set alternative services for |origin|. Previous alternative services for // |origin| are discarded. diff --git a/chromium/net/http/http_server_properties_impl.cc b/chromium/net/http/http_server_properties_impl.cc index 15871b53086..6278f3627bf 100644 --- a/chromium/net/http/http_server_properties_impl.cc +++ b/chromium/net/http/http_server_properties_impl.cc @@ -83,6 +83,7 @@ void HttpServerPropertiesImpl::InitializeAlternativeServiceServers( for (AlternativeServiceMap::reverse_iterator input_it = alternative_service_map->rbegin(); input_it != alternative_service_map->rend(); ++input_it) { + DCHECK(!input_it->second.empty()); AlternativeServiceMap::iterator output_it = alternative_service_map_.Peek(input_it->first); if (output_it == alternative_service_map_.end()) { @@ -117,7 +118,8 @@ void HttpServerPropertiesImpl::InitializeAlternativeServiceServers( for (AlternativeServiceMap::const_iterator it = alternative_service_map_.begin(); it != alternative_service_map_.end(); ++it) { - if (base::EndsWith(it->first.host(), canonical_suffixes_[i], false)) { + if (base::EndsWith(it->first.host(), canonical_suffixes_[i], + base::CompareCase::INSENSITIVE_ASCII)) { canonical_host_to_origin_map_[canonical_host] = it->first; break; } @@ -260,7 +262,8 @@ std::string HttpServerPropertiesImpl::GetCanonicalSuffix( // suffix. for (size_t i = 0; i < canonical_suffixes_.size(); ++i) { std::string canonical_suffix = canonical_suffixes_[i]; - if (base::EndsWith(host, canonical_suffixes_[i], false)) { + if (base::EndsWith(host, canonical_suffixes_[i], + base::CompareCase::INSENSITIVE_ASCII)) { return canonical_suffix; } } @@ -272,20 +275,37 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices( // Copy alternative services with probability greater than or equal to the // threshold into |alternative_services_above_threshold|. AlternativeServiceVector alternative_services_above_threshold; - AlternativeServiceMap::const_iterator it = - alternative_service_map_.Get(origin); - if (it != alternative_service_map_.end()) { - for (const AlternativeServiceInfo& alternative_service_info : it->second) { - if (alternative_service_info.probability < - alternative_service_probability_threshold_) { + const base::Time now = base::Time::Now(); + AlternativeServiceMap::iterator map_it = alternative_service_map_.Get(origin); + if (map_it != alternative_service_map_.end()) { + for (AlternativeServiceInfoVector::iterator it = map_it->second.begin(); + it != map_it->second.end();) { + if (it->expiration < now) { + it = map_it->second.erase(it); continue; } - AlternativeService alternative_service( - alternative_service_info.alternative_service); + if (it->probability < alternative_service_probability_threshold_) { + ++it; + continue; + } + AlternativeService alternative_service(it->alternative_service); if (alternative_service.host.empty()) { alternative_service.host = origin.host(); } + // If the alternative service is equivalent to the origin (same host, same + // port, and both TCP), then there is already a Job for it, so do not + // return it here. + if (origin.Equals(alternative_service.host_port_pair()) && + NPN_SPDY_MINIMUM_VERSION <= alternative_service.protocol && + alternative_service.protocol <= NPN_SPDY_MAXIMUM_VERSION) { + ++it; + continue; + } alternative_services_above_threshold.push_back(alternative_service); + ++it; + } + if (map_it->second.empty()) { + alternative_service_map_.Erase(map_it); } return alternative_services_above_threshold; } @@ -294,27 +314,37 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices( if (canonical == canonical_host_to_origin_map_.end()) { return AlternativeServiceVector(); } - it = alternative_service_map_.Get(canonical->second); - if (it == alternative_service_map_.end()) { + map_it = alternative_service_map_.Get(canonical->second); + if (map_it == alternative_service_map_.end()) { return AlternativeServiceVector(); } - for (const AlternativeServiceInfo& alternative_service_info : it->second) { - if (alternative_service_info.probability < - alternative_service_probability_threshold_) { + for (AlternativeServiceInfoVector::iterator it = map_it->second.begin(); + it != map_it->second.end();) { + if (it->expiration < now) { + it = map_it->second.erase(it); continue; } - AlternativeService alternative_service( - alternative_service_info.alternative_service); + if (it->probability < alternative_service_probability_threshold_) { + ++it; + continue; + } + AlternativeService alternative_service(it->alternative_service); if (alternative_service.host.empty()) { alternative_service.host = canonical->second.host(); if (IsAlternativeServiceBroken(alternative_service)) { + ++it; continue; } alternative_service.host = origin.host(); } else if (IsAlternativeServiceBroken(alternative_service)) { + ++it; continue; } alternative_services_above_threshold.push_back(alternative_service); + ++it; + } + if (map_it->second.empty()) { + alternative_service_map_.Erase(map_it); } return alternative_services_above_threshold; } @@ -322,11 +352,13 @@ AlternativeServiceVector HttpServerPropertiesImpl::GetAlternativeServices( bool HttpServerPropertiesImpl::SetAlternativeService( const HostPortPair& origin, const AlternativeService& alternative_service, - double alternative_probability) { + double alternative_probability, + base::Time expiration) { return SetAlternativeServices( origin, AlternativeServiceInfoVector( - /*size=*/1, AlternativeServiceInfo(alternative_service, - alternative_probability))); + /*size=*/1, + AlternativeServiceInfo(alternative_service, + alternative_probability, expiration))); } bool HttpServerPropertiesImpl::SetAlternativeServices( @@ -368,7 +400,8 @@ bool HttpServerPropertiesImpl::SetAlternativeServices( // canonical host. for (size_t i = 0; i < canonical_suffixes_.size(); ++i) { std::string canonical_suffix = canonical_suffixes_[i]; - if (base::EndsWith(origin.host(), canonical_suffixes_[i], false)) { + if (base::EndsWith(origin.host(), canonical_suffixes_[i], + base::CompareCase::INSENSITIVE_ASCII)) { HostPortPair canonical_host(canonical_suffix, origin.port()); canonical_host_to_origin_map_[canonical_host] = origin; break; @@ -611,7 +644,8 @@ HttpServerPropertiesImpl::CanonicalHostMap::const_iterator HttpServerPropertiesImpl::GetCanonicalHost(HostPortPair server) const { for (size_t i = 0; i < canonical_suffixes_.size(); ++i) { std::string canonical_suffix = canonical_suffixes_[i]; - if (base::EndsWith(server.host(), canonical_suffixes_[i], false)) { + if (base::EndsWith(server.host(), canonical_suffixes_[i], + base::CompareCase::INSENSITIVE_ASCII)) { HostPortPair canonical_host(canonical_suffix, server.port()); return canonical_host_to_origin_map_.find(canonical_host); } @@ -641,11 +675,38 @@ void HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings() { break; } - const AlternativeService alternative_service = it->first; + const AlternativeService expired_alternative_service = it->first; broken_alternative_services_.erase(it); - // TODO(bnc): Make sure broken alternative services are not in the mapping. - ClearAlternativeServices( - HostPortPair(alternative_service.host, alternative_service.port)); + + // Remove every occurrence of |expired_alternative_service| from + // |alternative_service_map_|. + for (AlternativeServiceMap::iterator map_it = + alternative_service_map_.begin(); + map_it != alternative_service_map_.end();) { + for (AlternativeServiceInfoVector::iterator it = map_it->second.begin(); + it != map_it->second.end();) { + AlternativeService alternative_service(it->alternative_service); + // Empty hostname in map means hostname of key: substitute before + // comparing to |expired_alternative_service|. + if (alternative_service.host.empty()) { + alternative_service.host = map_it->first.host(); + } + if (alternative_service == expired_alternative_service) { + it = map_it->second.erase(it); + continue; + } + ++it; + } + // If an origin has an empty list of alternative services, then remove it + // from both |canonical_host_to_origin_map_| and + // |alternative_service_map_|. + if (map_it->second.empty()) { + RemoveCanonicalHost(map_it->first); + map_it = alternative_service_map_.Erase(map_it); + continue; + } + ++map_it; + } } ScheduleBrokenAlternateProtocolMappingsExpiration(); } diff --git a/chromium/net/http/http_server_properties_impl.h b/chromium/net/http/http_server_properties_impl.h index 3abf5c83f4c..d6ee31a684f 100644 --- a/chromium/net/http/http_server_properties_impl.h +++ b/chromium/net/http/http_server_properties_impl.h @@ -13,7 +13,6 @@ #include "base/basictypes.h" #include "base/containers/hash_tables.h" -#include "base/gtest_prod_util.h" #include "base/threading/non_thread_safe.h" #include "base/values.h" #include "net/base/host_port_pair.h" @@ -91,7 +90,8 @@ class NET_EXPORT HttpServerPropertiesImpl const HostPortPair& origin) override; bool SetAlternativeService(const HostPortPair& origin, const AlternativeService& alternative_service, - double alternative_probability) override; + double alternative_probability, + base::Time expiration) override; bool SetAlternativeServices(const HostPortPair& origin, const AlternativeServiceInfoVector& alternative_service_info_vector) override; diff --git a/chromium/net/http/http_server_properties_impl_unittest.cc b/chromium/net/http/http_server_properties_impl_unittest.cc index 23cb395d84c..e354b77c53d 100644 --- a/chromium/net/http/http_server_properties_impl_unittest.cc +++ b/chromium/net/http/http_server_properties_impl_unittest.cc @@ -55,6 +55,15 @@ class HttpServerPropertiesImplTest : public testing::Test { return !alternative_service_vector.empty(); } + bool SetAlternativeService(const HostPortPair& origin, + const AlternativeService& alternative_service, + double alternative_probability) { + const base::Time expiration = + base::Time::Now() + base::TimeDelta::FromDays(1); + return impl_.SetAlternativeService(origin, alternative_service, + alternative_probability, expiration); + } + HttpServerPropertiesImpl impl_; }; @@ -124,14 +133,14 @@ TEST_F(SpdyServerPropertiesTest, SupportsRequestPriorityTest) { // Add www.youtube.com:443 as supporting QUIC. HostPortPair quic_server_youtube("www.youtube.com", 443); const AlternativeService alternative_service1(QUIC, "www.youtube.com", 443); - impl_.SetAlternativeService(quic_server_youtube, alternative_service1, 1.0); + SetAlternativeService(quic_server_youtube, alternative_service1, 1.0); EXPECT_TRUE(impl_.SupportsRequestPriority(quic_server_youtube)); // Add www.example.com:443 with two alternative services, one supporting QUIC. HostPortPair quic_server_example("www.example.com", 443); const AlternativeService alternative_service2(NPN_HTTP_2, "", 443); - impl_.SetAlternativeService(quic_server_example, alternative_service2, 1.0); - impl_.SetAlternativeService(quic_server_example, alternative_service1, 1.0); + SetAlternativeService(quic_server_example, alternative_service2, 1.0); + SetAlternativeService(quic_server_example, alternative_service1, 1.0); EXPECT_TRUE(impl_.SupportsRequestPriority(quic_server_example)); // Verify all the entries are the same after additions. @@ -259,7 +268,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Basic) { EXPECT_FALSE(HasAlternativeService(test_host_port_pair)); AlternativeService alternative_service(NPN_HTTP_2, "foo", 443); - impl_.SetAlternativeService(test_host_port_pair, alternative_service, 1.0); + SetAlternativeService(test_host_port_pair, alternative_service, 1.0); const AlternativeServiceVector alternative_service_vector = impl_.GetAlternativeServices(test_host_port_pair); ASSERT_EQ(1u, alternative_service_vector.size()); @@ -269,10 +278,42 @@ TEST_F(AlternateProtocolServerPropertiesTest, Basic) { EXPECT_FALSE(HasAlternativeService(test_host_port_pair)); } +TEST_F(AlternateProtocolServerPropertiesTest, ExcludeOrigin) { + AlternativeServiceInfoVector alternative_service_info_vector; + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); + // Same hostname, same port, TCP: should be ignored. + AlternativeService alternative_service1(NPN_HTTP_2, "foo", 443); + alternative_service_info_vector.push_back( + AlternativeServiceInfo(alternative_service1, 1.0, expiration)); + // Different hostname: GetAlternativeServices should return this one. + AlternativeService alternative_service2(NPN_HTTP_2, "bar", 443); + alternative_service_info_vector.push_back( + AlternativeServiceInfo(alternative_service2, 1.0, expiration)); + // Different port: GetAlternativeServices should return this one too. + AlternativeService alternative_service3(NPN_HTTP_2, "foo", 80); + alternative_service_info_vector.push_back( + AlternativeServiceInfo(alternative_service3, 1.0, expiration)); + // QUIC: GetAlternativeServices should return this one too. + AlternativeService alternative_service4(QUIC, "foo", 443); + alternative_service_info_vector.push_back( + AlternativeServiceInfo(alternative_service4, 1.0, expiration)); + + HostPortPair test_host_port_pair("foo", 443); + impl_.SetAlternativeServices(test_host_port_pair, + alternative_service_info_vector); + + const AlternativeServiceVector alternative_service_vector = + impl_.GetAlternativeServices(test_host_port_pair); + ASSERT_EQ(3u, alternative_service_vector.size()); + EXPECT_EQ(alternative_service2, alternative_service_vector[0]); + EXPECT_EQ(alternative_service3, alternative_service_vector[1]); + EXPECT_EQ(alternative_service4, alternative_service_vector[2]); +} + TEST_F(AlternateProtocolServerPropertiesTest, DefaultProbabilityExcluded) { HostPortPair test_host_port_pair("foo", 80); const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443); - impl_.SetAlternativeService(test_host_port_pair, alternative_service, 0.99); + SetAlternativeService(test_host_port_pair, alternative_service, 0.99); EXPECT_FALSE(HasAlternativeService(test_host_port_pair)); } @@ -283,18 +324,19 @@ TEST_F(AlternateProtocolServerPropertiesTest, Probability) { impl_.SetAlternativeServiceProbabilityThreshold(0.5); AlternativeServiceInfoVector alternative_service_info_vector; + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); const AlternativeService alternative_service1(NPN_HTTP_2, "foo", 443); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service1, 0.3)); + AlternativeServiceInfo(alternative_service1, 0.3, expiration)); const AlternativeService alternative_service2(QUIC, "bar", 123); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service2, 0.7)); + AlternativeServiceInfo(alternative_service2, 0.7, expiration)); const AlternativeService alternative_service3(NPN_SPDY_3_1, "baz", 443); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service3, 0.4)); + AlternativeServiceInfo(alternative_service3, 0.4, expiration)); const AlternativeService alternative_service4(NPN_HTTP_2, "qux", 1234); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service4, 0.6)); + AlternativeServiceInfo(alternative_service4, 0.6, expiration)); HostPortPair test_host_port_pair("foo", 80); impl_.SetAlternativeServices(test_host_port_pair, @@ -312,7 +354,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, ProbabilityExcluded) { HostPortPair test_host_port_pair("foo", 80); const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443); - impl_.SetAlternativeService(test_host_port_pair, alternative_service, 0.5); + SetAlternativeService(test_host_port_pair, alternative_service, 0.5); EXPECT_FALSE(HasAlternativeService(test_host_port_pair)); } @@ -321,18 +363,23 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) { // and thus will be removed by InitializeAlternativeServiceServers(). HostPortPair test_host_port_pair1("foo1", 80); const AlternativeService alternative_service1(NPN_HTTP_2, "bar1", 443); - impl_.SetAlternativeService(test_host_port_pair1, alternative_service1, 1.0); + const base::Time now = base::Time::Now(); + base::Time expiration1 = now + base::TimeDelta::FromDays(1); + impl_.SetAlternativeService(test_host_port_pair1, alternative_service1, 1.0, + expiration1); // |test_host_port_pair2| has two alternative services. The broken one will // remain, the non-broken one will be removed by // InitializeAlternativeServiceServers(). AlternativeServiceInfoVector alternative_service_info_vector; const AlternativeService alternative_service2(NPN_SPDY_3_1, "bar2", 443); + base::Time expiration2 = now + base::TimeDelta::FromDays(2); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service2, 1.0)); + AlternativeServiceInfo(alternative_service2, 1.0, expiration2)); const AlternativeService alternative_service3(NPN_SPDY_3_1, "bar3", 1234); + base::Time expiration3 = now + base::TimeDelta::FromDays(3); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service3, 0.8)); + AlternativeServiceInfo(alternative_service3, 0.8, expiration3)); HostPortPair test_host_port_pair2("foo2", 80); impl_.SetAlternativeServices(test_host_port_pair2, alternative_service_info_vector); @@ -343,16 +390,18 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) { AlternativeServiceMap alternative_service_map( AlternativeServiceMap::NO_AUTO_EVICT); const AlternativeService alternative_service4(NPN_HTTP_2, "bar4", 123); + base::Time expiration4 = now + base::TimeDelta::FromDays(4); const AlternativeServiceInfo alternative_service_info1(alternative_service4, - 0.7); + 0.7, expiration4); alternative_service_map.Put( test_host_port_pair2, AlternativeServiceInfoVector(/*size=*/1, alternative_service_info1)); HostPortPair test_host_port_pair3("foo3", 80); const AlternativeService alternative_service5(NPN_HTTP_2, "bar5", 1234); + base::Time expiration5 = now + base::TimeDelta::FromDays(5); const AlternativeServiceInfo alternative_service_info2(alternative_service5, - 0.2); + 0.2, expiration5); alternative_service_map.Put( test_host_port_pair3, AlternativeServiceInfoVector(/*size=*/1, alternative_service_info2)); @@ -367,13 +416,16 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) { ASSERT_EQ(1u, map_it->second.size()); EXPECT_EQ(alternative_service5, map_it->second[0].alternative_service); EXPECT_EQ(0.2, map_it->second[0].probability); + EXPECT_EQ(expiration5, map_it->second[0].expiration); ++map_it; EXPECT_TRUE(map_it->first.Equals(test_host_port_pair2)); ASSERT_EQ(2u, map_it->second.size()); EXPECT_EQ(alternative_service2, map_it->second[0].alternative_service); EXPECT_EQ(1.0, map_it->second[0].probability); + EXPECT_EQ(expiration2, map_it->second[0].expiration); EXPECT_EQ(alternative_service4, map_it->second[1].alternative_service); EXPECT_EQ(0.7, map_it->second[1].probability); + EXPECT_EQ(expiration4, map_it->second[1].expiration); } // Regression test for https://crbug.com/504032: @@ -385,8 +437,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, InitializeWithEmptyHostname) { "", 1234); const AlternativeService alternative_service_with_foo_hostname(NPN_HTTP_2, "foo", 1234); - impl_.SetAlternativeService(host_port_pair, - alternative_service_with_empty_hostname, 1.0); + SetAlternativeService(host_port_pair, alternative_service_with_empty_hostname, + 1.0); impl_.MarkAlternativeServiceBroken(alternative_service_with_foo_hostname); AlternativeServiceMap alternative_service_map( @@ -402,13 +454,89 @@ TEST_F(AlternateProtocolServerPropertiesTest, InitializeWithEmptyHostname) { alternative_service_vector[0]); } +// Regression test for https://crbug.com/516486: +// GetAlternativeServices() should remove |alternative_service_map_| elements +// with empty value. +TEST_F(AlternateProtocolServerPropertiesTest, EmptyVector) { + HostPortPair host_port_pair("foo", 443); + const AlternativeService alternative_service(NPN_HTTP_2, "bar", 443); + base::Time expiration = base::Time::Now() - base::TimeDelta::FromDays(1); + const AlternativeServiceInfo alternative_service_info(alternative_service, + 1.0, expiration); + AlternativeServiceMap alternative_service_map( + AlternativeServiceMap::NO_AUTO_EVICT); + alternative_service_map.Put( + host_port_pair, + AlternativeServiceInfoVector(/*size=*/1, alternative_service_info)); + + // Prepare |alternative_service_map_| with a single key that has a single + // AlternativeServiceInfo with identical hostname and port. + impl_.InitializeAlternativeServiceServers(&alternative_service_map); + + // GetAlternativeServices() should remove such AlternativeServiceInfo from + // |alternative_service_map_|, emptying the AlternativeServiceInfoVector + // corresponding to |host_port_pair|. + AlternativeServiceVector alternative_service_vector = + impl_.GetAlternativeServices(host_port_pair); + ASSERT_TRUE(alternative_service_vector.empty()); + + // GetAlternativeServices() should remove this key from + // |alternative_service_map_|, and SetAlternativeServices() should not crash. + impl_.SetAlternativeServices( + host_port_pair, + AlternativeServiceInfoVector(/*size=*/1, alternative_service_info)); + + // There should still be no alternative service assigned to |host_port_pair|. + alternative_service_vector = impl_.GetAlternativeServices(host_port_pair); + ASSERT_TRUE(alternative_service_vector.empty()); +} + +// Regression test for https://crbug.com/516486 for the canonical host case. +TEST_F(AlternateProtocolServerPropertiesTest, EmptyVectorForCanonical) { + HostPortPair host_port_pair("foo.c.youtube.com", 443); + HostPortPair canonical_host_port_pair("bar.c.youtube.com", 443); + const AlternativeService alternative_service(NPN_HTTP_2, "", 443); + base::Time expiration = base::Time::Now() - base::TimeDelta::FromDays(1); + const AlternativeServiceInfo alternative_service_info(alternative_service, + 1.0, expiration); + AlternativeServiceMap alternative_service_map( + AlternativeServiceMap::NO_AUTO_EVICT); + alternative_service_map.Put( + canonical_host_port_pair, + AlternativeServiceInfoVector(/*size=*/1, alternative_service_info)); + + // Prepare |alternative_service_map_| with a single key that has a single + // AlternativeServiceInfo with identical hostname and port. + impl_.InitializeAlternativeServiceServers(&alternative_service_map); + + // GetAlternativeServices() should remove such AlternativeServiceInfo from + // |alternative_service_map_|, emptying the AlternativeServiceInfoVector + // corresponding to |canonical_host_port_pair|, even when looking up + // alternative services for |host_port_pair|. + AlternativeServiceVector alternative_service_vector = + impl_.GetAlternativeServices(host_port_pair); + ASSERT_TRUE(alternative_service_vector.empty()); + + // GetAlternativeServices() should remove this key from + // |alternative_service_map_|, and SetAlternativeServices() should not crash. + impl_.SetAlternativeServices( + canonical_host_port_pair, + AlternativeServiceInfoVector(/*size=*/1, alternative_service_info)); + + // There should still be no alternative service assigned to + // |canonical_host_port_pair|. + alternative_service_vector = + impl_.GetAlternativeServices(canonical_host_port_pair); + ASSERT_TRUE(alternative_service_vector.empty()); +} + TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternativeServices) { HostPortPair test_host_port_pair1("foo1", 80); const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo1", 443); - impl_.SetAlternativeService(test_host_port_pair1, alternative_service1, 1.0); + SetAlternativeService(test_host_port_pair1, alternative_service1, 1.0); HostPortPair test_host_port_pair2("foo2", 80); const AlternativeService alternative_service2(NPN_HTTP_2, "foo2", 1234); - impl_.SetAlternativeService(test_host_port_pair2, alternative_service2, 1.0); + SetAlternativeService(test_host_port_pair2, alternative_service2, 1.0); const AlternativeServiceMap& map = impl_.alternative_service_map(); AlternativeServiceMap::const_iterator it = map.begin(); @@ -431,7 +559,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, MRUOfGetAlternativeServices) { TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) { HostPortPair test_host_port_pair("foo", 80); const AlternativeService alternative_service1(NPN_HTTP_2, "foo", 443); - impl_.SetAlternativeService(test_host_port_pair, alternative_service1, 1.0); + SetAlternativeService(test_host_port_pair, alternative_service1, 1.0); AlternativeServiceVector alternative_service_vector = impl_.GetAlternativeServices(test_host_port_pair); ASSERT_EQ(1u, alternative_service_vector.size()); @@ -448,11 +576,12 @@ TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) { // SetAlternativeServices should add a broken alternative service to the map. AlternativeServiceInfoVector alternative_service_info_vector; + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service1, 1.0)); + AlternativeServiceInfo(alternative_service1, 1.0, expiration)); const AlternativeService alternative_service2(NPN_HTTP_2, "foo", 1234); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service2, 1.0)); + AlternativeServiceInfo(alternative_service2, 1.0, expiration)); impl_.SetAlternativeServices(test_host_port_pair, alternative_service_info_vector); alternative_service_vector = @@ -464,7 +593,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) { EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service_vector[1])); // SetAlternativeService should add a broken alternative service to the map. - impl_.SetAlternativeService(test_host_port_pair, alternative_service1, 1.0); + SetAlternativeService(test_host_port_pair, alternative_service1, 1.0); alternative_service_vector = impl_.GetAlternativeServices(test_host_port_pair); ASSERT_EQ(1u, alternative_service_vector.size()); @@ -472,14 +601,70 @@ TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) { EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service_vector[0])); } +TEST_F(AlternateProtocolServerPropertiesTest, MaxAge) { + AlternativeServiceInfoVector alternative_service_info_vector; + base::Time now = base::Time::Now(); + base::TimeDelta one_day = base::TimeDelta::FromDays(1); + + // First alternative service expired one day ago, should not be returned by + // GetAlternativeServices(). + const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo", 443); + alternative_service_info_vector.push_back( + AlternativeServiceInfo(alternative_service1, 1.0, now - one_day)); + + // Second alterrnative service will expire one day from now, should be + // returned by GetAlternativeSerices(). + const AlternativeService alternative_service2(NPN_HTTP_2, "bar", 1234); + alternative_service_info_vector.push_back( + AlternativeServiceInfo(alternative_service2, 1.0, now + one_day)); + + HostPortPair test_host_port_pair("foo", 80); + impl_.SetAlternativeServices(test_host_port_pair, + alternative_service_info_vector); + + AlternativeServiceVector alternative_service_vector = + impl_.GetAlternativeServices(test_host_port_pair); + ASSERT_EQ(1u, alternative_service_vector.size()); + EXPECT_EQ(alternative_service2, alternative_service_vector[0]); +} + +TEST_F(AlternateProtocolServerPropertiesTest, MaxAgeCanonical) { + AlternativeServiceInfoVector alternative_service_info_vector; + base::Time now = base::Time::Now(); + base::TimeDelta one_day = base::TimeDelta::FromDays(1); + + // First alternative service expired one day ago, should not be returned by + // GetAlternativeServices(). + const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo", 443); + alternative_service_info_vector.push_back( + AlternativeServiceInfo(alternative_service1, 1.0, now - one_day)); + + // Second alterrnative service will expire one day from now, should be + // returned by GetAlternativeSerices(). + const AlternativeService alternative_service2(NPN_HTTP_2, "bar", 1234); + alternative_service_info_vector.push_back( + AlternativeServiceInfo(alternative_service2, 1.0, now + one_day)); + + HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80); + impl_.SetAlternativeServices(canonical_host_port_pair, + alternative_service_info_vector); + + HostPortPair test_host_port_pair("foo.c.youtube.com", 80); + AlternativeServiceVector alternative_service_vector = + impl_.GetAlternativeServices(test_host_port_pair); + ASSERT_EQ(1u, alternative_service_vector.size()); + EXPECT_EQ(alternative_service2, alternative_service_vector[0]); +} + TEST_F(AlternateProtocolServerPropertiesTest, ClearAlternativeServices) { AlternativeServiceInfoVector alternative_service_info_vector; const AlternativeService alternative_service1(NPN_SPDY_3_1, "foo", 443); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service1, 1.0)); + AlternativeServiceInfo(alternative_service1, 1.0, expiration)); const AlternativeService alternative_service2(NPN_HTTP_2, "bar", 1234); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service2, 1.0)); + AlternativeServiceInfo(alternative_service2, 1.0, expiration)); HostPortPair test_host_port_pair("foo", 80); impl_.SetAlternativeServices(test_host_port_pair, alternative_service_info_vector); @@ -504,8 +689,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) { HostPortPair canonical_host_port_pair("bar.c.youtube.com", 80); AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com", 1234); - impl_.SetAlternativeService(canonical_host_port_pair, - canonical_alternative_service, 1.0); + SetAlternativeService(canonical_host_port_pair, canonical_alternative_service, + 1.0); AlternativeServiceVector alternative_service_vector = impl_.GetAlternativeServices(test_host_port_pair); ASSERT_EQ(1u, alternative_service_vector.size()); @@ -515,8 +700,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) { impl_.MarkAlternativeServiceBroken(broken_alternative_service); EXPECT_TRUE(impl_.IsAlternativeServiceBroken(broken_alternative_service)); - impl_.SetAlternativeService(test_host_port_pair, broken_alternative_service, - 1.0); + SetAlternativeService(test_host_port_pair, broken_alternative_service, 1.0); alternative_service_vector = impl_.GetAlternativeServices(test_host_port_pair); ASSERT_EQ(1u, alternative_service_vector.size()); @@ -527,7 +711,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, BrokenShadowsCanonical) { TEST_F(AlternateProtocolServerPropertiesTest, ClearBroken) { HostPortPair test_host_port_pair("foo", 80); const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443); - impl_.SetAlternativeService(test_host_port_pair, alternative_service, 1.0); + SetAlternativeService(test_host_port_pair, alternative_service, 1.0); impl_.MarkAlternativeServiceBroken(alternative_service); ASSERT_TRUE(HasAlternativeService(test_host_port_pair)); EXPECT_TRUE(impl_.IsAlternativeServiceBroken(alternative_service)); @@ -540,7 +724,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, ClearBroken) { TEST_F(AlternateProtocolServerPropertiesTest, MarkRecentlyBroken) { HostPortPair host_port_pair("foo", 80); const AlternativeService alternative_service(NPN_HTTP_2, "foo", 443); - impl_.SetAlternativeService(host_port_pair, alternative_service, 1.0); + SetAlternativeService(host_port_pair, alternative_service, 1.0); EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service)); EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service)); @@ -564,11 +748,12 @@ TEST_F(AlternateProtocolServerPropertiesTest, Canonical) { AlternativeServiceInfoVector alternative_service_info_vector; const AlternativeService canonical_alternative_service1( QUIC, "bar.c.youtube.com", 1234); + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); alternative_service_info_vector.push_back( - AlternativeServiceInfo(canonical_alternative_service1, 1.0)); + AlternativeServiceInfo(canonical_alternative_service1, 1.0, expiration)); const AlternativeService canonical_alternative_service2(NPN_HTTP_2, "", 443); alternative_service_info_vector.push_back( - AlternativeServiceInfo(canonical_alternative_service2, 1.0)); + AlternativeServiceInfo(canonical_alternative_service2, 1.0, expiration)); impl_.SetAlternativeServices(canonical_host_port_pair, alternative_service_info_vector); @@ -603,8 +788,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBelowThreshold) { AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com", 1234); - impl_.SetAlternativeService(canonical_host_port_pair, - canonical_alternative_service, 0.01); + SetAlternativeService(canonical_host_port_pair, canonical_alternative_service, + 0.01); EXPECT_FALSE(HasAlternativeService(canonical_host_port_pair)); EXPECT_FALSE(HasAlternativeService(test_host_port_pair)); } @@ -617,8 +802,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalAboveThreshold) { AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com", 1234); - impl_.SetAlternativeService(canonical_host_port_pair, - canonical_alternative_service, 0.03); + SetAlternativeService(canonical_host_port_pair, canonical_alternative_service, + 0.03); EXPECT_TRUE(HasAlternativeService(canonical_host_port_pair)); EXPECT_TRUE(HasAlternativeService(test_host_port_pair)); } @@ -629,8 +814,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, ClearCanonical) { AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com", 1234); - impl_.SetAlternativeService(canonical_host_port_pair, - canonical_alternative_service, 1.0); + SetAlternativeService(canonical_host_port_pair, canonical_alternative_service, + 1.0); impl_.ClearAlternativeServices(canonical_host_port_pair); EXPECT_FALSE(HasAlternativeService(test_host_port_pair)); } @@ -641,8 +826,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBroken) { AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com", 1234); - impl_.SetAlternativeService(canonical_host_port_pair, - canonical_alternative_service, 1.0); + SetAlternativeService(canonical_host_port_pair, canonical_alternative_service, + 1.0); impl_.MarkAlternativeServiceBroken(canonical_alternative_service); EXPECT_FALSE(HasAlternativeService(test_host_port_pair)); } @@ -652,7 +837,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalOverride) { HostPortPair test_host_port_pair("foo.c.youtube.com", 80); HostPortPair bar_host_port_pair("bar.c.youtube.com", 80); AlternativeService bar_alternative_service(QUIC, "bar.c.youtube.com", 1234); - impl_.SetAlternativeService(bar_host_port_pair, bar_alternative_service, 1.0); + SetAlternativeService(bar_host_port_pair, bar_alternative_service, 1.0); AlternativeServiceVector alternative_service_vector = impl_.GetAlternativeServices(test_host_port_pair); ASSERT_EQ(1u, alternative_service_vector.size()); @@ -660,7 +845,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, CanonicalOverride) { HostPortPair qux_host_port_pair("qux.c.youtube.com", 80); AlternativeService qux_alternative_service(QUIC, "qux.c.youtube.com", 443); - impl_.SetAlternativeService(qux_host_port_pair, qux_alternative_service, 1.0); + SetAlternativeService(qux_host_port_pair, qux_alternative_service, 1.0); alternative_service_vector = impl_.GetAlternativeServices(test_host_port_pair); ASSERT_EQ(1u, alternative_service_vector.size()); @@ -673,8 +858,8 @@ TEST_F(AlternateProtocolServerPropertiesTest, ClearWithCanonical) { AlternativeService canonical_alternative_service(QUIC, "bar.c.youtube.com", 1234); - impl_.SetAlternativeService(canonical_host_port_pair, - canonical_alternative_service, 1.0); + SetAlternativeService(canonical_host_port_pair, canonical_alternative_service, + 1.0); impl_.Clear(); EXPECT_FALSE(HasAlternativeService(test_host_port_pair)); } @@ -683,7 +868,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, ExpireBrokenAlternateProtocolMappings) { HostPortPair host_port_pair("foo", 443); AlternativeService alternative_service(QUIC, "foo", 443); - impl_.SetAlternativeService(host_port_pair, alternative_service, 1.0); + SetAlternativeService(host_port_pair, alternative_service, 1.0); EXPECT_TRUE(HasAlternativeService(host_port_pair)); EXPECT_FALSE(impl_.IsAlternativeServiceBroken(alternative_service)); EXPECT_FALSE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service)); @@ -700,6 +885,45 @@ TEST_F(AlternateProtocolServerPropertiesTest, EXPECT_TRUE(impl_.WasAlternativeServiceRecentlyBroken(alternative_service)); } +// Regression test for https://crbug.com/505413. +TEST_F(AlternateProtocolServerPropertiesTest, RemoveExpiredBrokenAltSvc) { + HostPortPair foo_host_port_pair("foo", 443); + AlternativeService bar_alternative_service(QUIC, "bar", 443); + SetAlternativeService(foo_host_port_pair, bar_alternative_service, 1.0); + EXPECT_TRUE(HasAlternativeService(foo_host_port_pair)); + + HostPortPair bar_host_port_pair1("bar", 80); + AlternativeService nohost_alternative_service(QUIC, "", 443); + SetAlternativeService(bar_host_port_pair1, nohost_alternative_service, 1.0); + EXPECT_TRUE(HasAlternativeService(bar_host_port_pair1)); + + HostPortPair bar_host_port_pair2("bar", 443); + AlternativeService baz_alternative_service(QUIC, "baz", 1234); + SetAlternativeService(bar_host_port_pair2, baz_alternative_service, 1.0); + EXPECT_TRUE(HasAlternativeService(bar_host_port_pair2)); + + // Mark "bar:443" as broken. + base::TimeTicks past = + base::TimeTicks::Now() - base::TimeDelta::FromSeconds(42); + HttpServerPropertiesImplPeer::AddBrokenAlternativeServiceWithExpirationTime( + impl_, bar_alternative_service, past); + + // Expire brokenness of "bar:443". + HttpServerPropertiesImplPeer::ExpireBrokenAlternateProtocolMappings(impl_); + + // "foo:443" should have no alternative service now. + EXPECT_FALSE(HasAlternativeService(foo_host_port_pair)); + // "bar:80" should have no alternative service now. + EXPECT_FALSE(HasAlternativeService(bar_host_port_pair1)); + // The alternative service of "bar:443" should be unaffected. + EXPECT_TRUE(HasAlternativeService(bar_host_port_pair2)); + + EXPECT_TRUE( + impl_.WasAlternativeServiceRecentlyBroken(bar_alternative_service)); + EXPECT_FALSE( + impl_.WasAlternativeServiceRecentlyBroken(baz_alternative_service)); +} + typedef HttpServerPropertiesImplTest SpdySettingsServerPropertiesTest; TEST_F(SpdySettingsServerPropertiesTest, Initialize) { diff --git a/chromium/net/http/http_server_properties_manager.cc b/chromium/net/http/http_server_properties_manager.cc index d89efab5a41..2577f953cd8 100644 --- a/chromium/net/http/http_server_properties_manager.cc +++ b/chromium/net/http/http_server_properties_manager.cc @@ -14,6 +14,7 @@ #include "base/thread_task_runner_handle.h" #include "base/values.h" #include "net/base/ip_address_number.h" +#include "net/base/port_util.h" namespace net { @@ -63,6 +64,7 @@ const char kProtocolKey[] = "protocol_str"; const char kHostKey[] = "host"; const char kPortKey[] = "port"; const char kProbabilityKey[] = "probability"; +const char kExpirationKey[] = "expiration"; const char kNetworkStatsKey[] = "network_stats"; const char kSrttKey[] = "srtt"; @@ -84,8 +86,7 @@ HttpServerPropertiesManager::HttpServerPropertiesManager( pref_weak_ptr_factory_.reset( new base::WeakPtrFactory<HttpServerPropertiesManager>(this)); pref_weak_ptr_ = pref_weak_ptr_factory_->GetWeakPtr(); - pref_cache_update_timer_.reset( - new base::OneShotTimer<HttpServerPropertiesManager>); + pref_cache_update_timer_.reset(new base::OneShotTimer); pref_change_registrar_.Init(pref_service_); pref_change_registrar_.Add( path_, @@ -104,8 +105,7 @@ void HttpServerPropertiesManager::InitializeOnNetworkThread() { new base::WeakPtrFactory<HttpServerPropertiesManager>(this)); http_server_properties_impl_.reset(new HttpServerPropertiesImpl()); - network_prefs_update_timer_.reset( - new base::OneShotTimer<HttpServerPropertiesManager>); + network_prefs_update_timer_.reset(new base::OneShotTimer); pref_task_runner_->PostTask( FROM_HERE, @@ -199,10 +199,11 @@ AlternativeServiceVector HttpServerPropertiesManager::GetAlternativeServices( bool HttpServerPropertiesManager::SetAlternativeService( const HostPortPair& origin, const AlternativeService& alternative_service, - double alternative_probability) { + double alternative_probability, + base::Time expiration) { DCHECK(network_task_runner_->RunsTasksOnCurrentThread()); const bool changed = http_server_properties_impl_->SetAlternativeService( - origin, alternative_service, alternative_probability); + origin, alternative_service, alternative_probability, expiration); if (changed) { ScheduleUpdatePrefsOnNetworkThread(SET_ALTERNATIVE_SERVICES); } @@ -523,32 +524,34 @@ void HttpServerPropertiesManager::AddToSpdySettingsMap( spdy_settings_map->Put(server, settings_map); } -AlternativeServiceInfo HttpServerPropertiesManager::ParseAlternativeServiceDict( +bool HttpServerPropertiesManager::ParseAlternativeServiceDict( const base::DictionaryValue& alternative_service_dict, - const std::string& server_str) { + const std::string& server_str, + AlternativeServiceInfo* alternative_service_info) { // Protocol is mandatory. std::string protocol_str; if (!alternative_service_dict.GetStringWithoutPathExpansion(kProtocolKey, &protocol_str)) { DVLOG(1) << "Malformed alternative service protocol string for server: " << server_str; - return AlternativeServiceInfo(); + return false; } AlternateProtocol protocol = AlternateProtocolFromString(protocol_str); if (!IsAlternateProtocolValid(protocol)) { DVLOG(1) << "Invalid alternative service protocol string for server: " << server_str; - return AlternativeServiceInfo(); + return false; } + alternative_service_info->alternative_service.protocol = protocol; // Host is optional, defaults to "". - std::string host; + alternative_service_info->alternative_service.host.clear(); if (alternative_service_dict.HasKey(kHostKey) && - !alternative_service_dict.GetStringWithoutPathExpansion(kHostKey, - &host)) { + !alternative_service_dict.GetStringWithoutPathExpansion( + kHostKey, &(alternative_service_info->alternative_service.host))) { DVLOG(1) << "Malformed alternative service host string for server: " << server_str; - return AlternativeServiceInfo(); + return false; } // Port is mandatory. @@ -556,21 +559,56 @@ AlternativeServiceInfo HttpServerPropertiesManager::ParseAlternativeServiceDict( if (!alternative_service_dict.GetInteger(kPortKey, &port) || !IsPortValid(port)) { DVLOG(1) << "Malformed alternative service port for server: " << server_str; - return AlternativeServiceInfo(); + return false; } + alternative_service_info->alternative_service.port = + static_cast<uint32>(port); // Probability is optional, defaults to 1.0. - double probability = 1.0; + alternative_service_info->probability = 1.0; if (alternative_service_dict.HasKey(kProbabilityKey) && - !alternative_service_dict.GetDoubleWithoutPathExpansion(kProbabilityKey, - &probability)) { + !alternative_service_dict.GetDoubleWithoutPathExpansion( + kProbabilityKey, &(alternative_service_info->probability))) { DVLOG(1) << "Malformed alternative service probability for server: " << server_str; - return AlternativeServiceInfo(); + return false; } - return AlternativeServiceInfo(protocol, host, static_cast<uint16>(port), - probability); + // Expiration is optional, defaults to one day. + base::Time expiration; + if (!alternative_service_dict.HasKey(kExpirationKey)) { + alternative_service_info->expiration = + base::Time::Now() + base::TimeDelta::FromDays(1); + return true; + } + + std::string expiration_string; + if (alternative_service_dict.GetStringWithoutPathExpansion( + kExpirationKey, &expiration_string)) { + int64 expiration_int64 = 0; + if (!base::StringToInt64(expiration_string, &expiration_int64)) { + DVLOG(1) << "Malformed alternative service expiration for server: " + << server_str; + return false; + } + alternative_service_info->expiration = + base::Time::FromInternalValue(expiration_int64); + return true; + } + + // Early release 46 Dev and Canary versions stored expiration as double. + // TODO(bnc) Remove the following code parsing double around 2015-10-01. + double expiration_double; + if (alternative_service_dict.GetDoubleWithoutPathExpansion( + kExpirationKey, &expiration_double)) { + alternative_service_info->expiration = + base::Time::FromDoubleT(expiration_double); + return true; + } + + DVLOG(1) << "Malformed alternative service expiration for server: " + << server_str; + return false; } bool HttpServerPropertiesManager::AddToAlternativeServiceMap( @@ -590,11 +628,10 @@ bool HttpServerPropertiesManager::AddToAlternativeServiceMap( if (!alternative_service_list_item->GetAsDictionary( &alternative_service_dict)) return false; - AlternativeServiceInfo alternative_service_info = - ParseAlternativeServiceDict(*alternative_service_dict, - server.ToString()); - if (alternative_service_info.alternative_service.protocol == - UNINITIALIZED_ALTERNATE_PROTOCOL) { + AlternativeServiceInfo alternative_service_info; + if (!ParseAlternativeServiceDict(*alternative_service_dict, + server.ToString(), + &alternative_service_info)) { return false; } alternative_service_info_vector.push_back(alternative_service_info); @@ -607,11 +644,10 @@ bool HttpServerPropertiesManager::AddToAlternativeServiceMap( kAlternateProtocolKey, &alternative_service_dict)) { return true; } - AlternativeServiceInfo alternative_service_info = - ParseAlternativeServiceDict(*alternative_service_dict, - server.ToString()); - if (alternative_service_info.alternative_service.protocol == - UNINITIALIZED_ALTERNATE_PROTOCOL) { + AlternativeServiceInfo alternative_service_info; + if (!ParseAlternativeServiceDict(*alternative_service_dict, + server.ToString(), + &alternative_service_info)) { return false; } alternative_service_info_vector.push_back(alternative_service_info); @@ -981,6 +1017,11 @@ void HttpServerPropertiesManager::SaveAlternativeServiceToServerPrefs( kProtocolKey, AlternateProtocolToString(alternative_service.protocol)); alternative_service_dict->SetDouble(kProbabilityKey, alternative_service_info.probability); + // JSON cannot store int64, so expiration is converted to a string. + alternative_service_dict->SetString( + kExpirationKey, + base::Int64ToString( + alternative_service_info.expiration.ToInternalValue())); alternative_service_list->Append(alternative_service_dict); } if (alternative_service_list->GetSize() == 0) diff --git a/chromium/net/http/http_server_properties_manager.h b/chromium/net/http/http_server_properties_manager.h index 3b8f155d6e4..1e09ff7a75d 100644 --- a/chromium/net/http/http_server_properties_manager.h +++ b/chromium/net/http/http_server_properties_manager.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/prefs/pref_change_registrar.h" @@ -91,7 +92,8 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties { const HostPortPair& origin) override; bool SetAlternativeService(const HostPortPair& origin, const AlternativeService& alternative_service, - double alternative_probability) override; + double alternative_probability, + base::Time expiration) override; bool SetAlternativeServices(const HostPortPair& origin, const AlternativeServiceInfoVector& alternative_service_info_vector) override; @@ -205,6 +207,10 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties { const base::Closure& completion); private: + FRIEND_TEST_ALL_PREFIXES(HttpServerPropertiesManagerTest, + AddToAlternativeServiceMap); + FRIEND_TEST_ALL_PREFIXES(HttpServerPropertiesManagerTest, + AlternativeServiceExpirationDouble); void OnHttpServerPropertiesChanged(); bool ReadSupportsQuic(const base::DictionaryValue& server_dict, @@ -212,9 +218,10 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties { void AddToSpdySettingsMap(const HostPortPair& server, const base::DictionaryValue& server_dict, SpdySettingsMap* spdy_settings_map); - AlternativeServiceInfo ParseAlternativeServiceDict( + bool ParseAlternativeServiceDict( const base::DictionaryValue& alternative_service_dict, - const std::string& server_str); + const std::string& server_str, + AlternativeServiceInfo* alternative_service_info); bool AddToAlternativeServiceMap( const HostPortPair& server, const base::DictionaryValue& server_dict, @@ -245,8 +252,7 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties { base::WeakPtr<HttpServerPropertiesManager> pref_weak_ptr_; // Used to post cache update tasks. - scoped_ptr<base::OneShotTimer<HttpServerPropertiesManager> > - pref_cache_update_timer_; + scoped_ptr<base::OneShotTimer> pref_cache_update_timer_; // Used to track the spdy servers changes. PrefChangeRegistrar pref_change_registrar_; @@ -261,8 +267,7 @@ class NET_EXPORT HttpServerPropertiesManager : public HttpServerProperties { const scoped_refptr<base::SequencedTaskRunner> network_task_runner_; // Used to post |prefs::kHttpServerProperties| pref update tasks. - scoped_ptr<base::OneShotTimer<HttpServerPropertiesManager> > - network_prefs_update_timer_; + scoped_ptr<base::OneShotTimer> network_prefs_update_timer_; scoped_ptr<HttpServerPropertiesImpl> http_server_properties_impl_; diff --git a/chromium/net/http/http_server_properties_manager_unittest.cc b/chromium/net/http/http_server_properties_manager_unittest.cc index 2a5d0497e2a..2164bb52485 100644 --- a/chromium/net/http/http_server_properties_manager_unittest.cc +++ b/chromium/net/http/http_server_properties_manager_unittest.cc @@ -5,6 +5,7 @@ #include "net/http/http_server_properties_manager.h" #include "base/basictypes.h" +#include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/message_loop/message_loop.h" #include "base/prefs/pref_registry_simple.h" @@ -100,11 +101,14 @@ class TestingHttpServerPropertiesManager : public HttpServerPropertiesManager { DISALLOW_COPY_AND_ASSIGN(TestingHttpServerPropertiesManager); }; +} // namespace + class HttpServerPropertiesManagerTest : public testing::Test { protected: HttpServerPropertiesManagerTest() {} void SetUp() override { + one_day_from_now_ = base::Time::Now() + base::TimeDelta::FromDays(1); pref_service_.registry()->RegisterDictionaryPref(kTestHttpServerProperties); http_server_props_manager_.reset( new StrictMock<TestingHttpServerPropertiesManager>( @@ -170,6 +174,7 @@ class HttpServerPropertiesManagerTest : public testing::Test { //base::RunLoop loop_; TestingPrefServiceSimple pref_service_; scoped_ptr<TestingHttpServerPropertiesManager> http_server_props_manager_; + base::Time one_day_from_now_; private: DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesManagerTest); @@ -192,7 +197,7 @@ TEST_F(HttpServerPropertiesManagerTest, // Set up alternative_services for www.google.com:80. base::DictionaryValue* alternative_service_dict0 = new base::DictionaryValue; alternative_service_dict0->SetInteger("port", 443); - alternative_service_dict0->SetString("protocol_str", "npn-spdy/3"); + alternative_service_dict0->SetString("protocol_str", "npn-h2"); base::DictionaryValue* alternative_service_dict1 = new base::DictionaryValue; alternative_service_dict1->SetInteger("port", 1234); alternative_service_dict1->SetString("protocol_str", "quic"); @@ -268,7 +273,7 @@ TEST_F(HttpServerPropertiesManagerTest, AlternativeServiceMap::const_iterator map_it = map.begin(); EXPECT_EQ("www.google.com", map_it->first.host()); ASSERT_EQ(2u, map_it->second.size()); - EXPECT_EQ(NPN_SPDY_3, map_it->second[0].alternative_service.protocol); + EXPECT_EQ(NPN_HTTP_2, map_it->second[0].alternative_service.protocol); EXPECT_TRUE(map_it->second[0].alternative_service.host.empty()); EXPECT_EQ(443, map_it->second[0].alternative_service.port); EXPECT_EQ(QUIC, map_it->second[1].alternative_service.protocol); @@ -308,7 +313,7 @@ TEST_F(HttpServerPropertiesManagerTest, BadCachedHostPortPair) { // Set up alternative_service for www.google.com:65536. base::DictionaryValue* alternative_service_dict = new base::DictionaryValue; - alternative_service_dict->SetString("protocol_str", "npn-spdy/3"); + alternative_service_dict->SetString("protocol_str", "npn-h2"); alternative_service_dict->SetInteger("port", 80); base::ListValue* alternative_service_list = new base::ListValue; alternative_service_list->Append(alternative_service_dict); @@ -361,7 +366,7 @@ TEST_F(HttpServerPropertiesManagerTest, BadCachedAltProtocolPort) { // Set up alternative_service for www.google.com:80. base::DictionaryValue* alternative_service_dict = new base::DictionaryValue; - alternative_service_dict->SetString("protocol_str", "npn-spdy/3"); + alternative_service_dict->SetString("protocol_str", "npn-h2"); alternative_service_dict->SetInteger("port", 65536); base::ListValue* alternative_service_list = new base::ListValue; alternative_service_list->Append(alternative_service_dict); @@ -524,11 +529,11 @@ TEST_F(HttpServerPropertiesManagerTest, GetAlternativeServices) { EXPECT_FALSE(HasAlternativeService(spdy_server_mail)); const AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 443); - http_server_props_manager_->SetAlternativeService(spdy_server_mail, - alternative_service, 1.0); + http_server_props_manager_->SetAlternativeService( + spdy_server_mail, alternative_service, 1.0, one_day_from_now_); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. - http_server_props_manager_->SetAlternativeService(spdy_server_mail, - alternative_service, 1.0); + http_server_props_manager_->SetAlternativeService( + spdy_server_mail, alternative_service, 1.0, one_day_from_now_); // Run the task. base::RunLoop().RunUntilIdle(); @@ -550,10 +555,10 @@ TEST_F(HttpServerPropertiesManagerTest, SetAlternativeServices) { const AlternativeService alternative_service1(NPN_HTTP_2, "mail.google.com", 443); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service1, 1.0)); + AlternativeServiceInfo(alternative_service1, 1.0, one_day_from_now_)); const AlternativeService alternative_service2(QUIC, "mail.google.com", 1234); alternative_service_info_vector.push_back( - AlternativeServiceInfo(alternative_service2, 1.0)); + AlternativeServiceInfo(alternative_service2, 1.0, one_day_from_now_)); http_server_props_manager_->SetAlternativeServices( spdy_server_mail, alternative_service_info_vector); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. @@ -594,8 +599,8 @@ TEST_F(HttpServerPropertiesManagerTest, ClearAlternativeServices) { HostPortPair spdy_server_mail("mail.google.com", 80); EXPECT_FALSE(HasAlternativeService(spdy_server_mail)); AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 443); - http_server_props_manager_->SetAlternativeService(spdy_server_mail, - alternative_service, 1.0); + http_server_props_manager_->SetAlternativeService( + spdy_server_mail, alternative_service, 1.0, one_day_from_now_); ExpectScheduleUpdatePrefsOnNetworkThread(); http_server_props_manager_->ClearAlternativeServices(spdy_server_mail); // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once. @@ -616,8 +621,8 @@ TEST_F(HttpServerPropertiesManagerTest, ConfirmAlternativeService) { AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 443); ExpectScheduleUpdatePrefsOnNetworkThread(); - http_server_props_manager_->SetAlternativeService(spdy_server_mail, - alternative_service, 1.0); + http_server_props_manager_->SetAlternativeService( + spdy_server_mail, alternative_service, 1.0, one_day_from_now_); EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken( alternative_service)); @@ -704,9 +709,9 @@ TEST_F(HttpServerPropertiesManagerTest, Clear) { HostPortPair spdy_server_mail("mail.google.com", 443); http_server_props_manager_->SetSupportsSpdy(spdy_server_mail, true); - AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 443); - http_server_props_manager_->SetAlternativeService(spdy_server_mail, - alternative_service, 1.0); + AlternativeService alternative_service(NPN_HTTP_2, "mail.google.com", 1234); + http_server_props_manager_->SetAlternativeService( + spdy_server_mail, alternative_service, 1.0, one_day_from_now_); IPAddressNumber actual_address; CHECK(ParseIPLiteralToNumber("127.0.0.1", &actual_address)); http_server_props_manager_->SetSupportsQuic(true, actual_address); @@ -776,7 +781,7 @@ TEST_F(HttpServerPropertiesManagerTest, BadSupportsQuic) { for (int i = 0; i < 200; ++i) { // Set up alternative_service for www.google.com:i. base::DictionaryValue* alternative_service_dict = new base::DictionaryValue; - alternative_service_dict->SetString("protocol_str", "npn-h2"); + alternative_service_dict->SetString("protocol_str", "quic"); alternative_service_dict->SetInteger("port", i); base::ListValue* alternative_service_list = new base::ListValue; alternative_service_list->Append(alternative_service_dict); @@ -820,7 +825,7 @@ TEST_F(HttpServerPropertiesManagerTest, BadSupportsQuic) { http_server_props_manager_->GetAlternativeServices( HostPortPair::FromString(server)); ASSERT_EQ(1u, alternative_service_vector.size()); - EXPECT_EQ(NPN_HTTP_2, alternative_service_vector[0].protocol); + EXPECT_EQ(QUIC, alternative_service_vector[0].protocol); EXPECT_EQ(i, alternative_service_vector[0].port); } @@ -839,19 +844,24 @@ TEST_F(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) { // Set alternate protocol. AlternativeServiceInfoVector alternative_service_info_vector; AlternativeService www_alternative_service1(NPN_HTTP_2, "", 443); + base::Time expiration1; + ASSERT_TRUE(base::Time::FromUTCString("2036-12-01 10:00:00", &expiration1)); alternative_service_info_vector.push_back( - AlternativeServiceInfo(www_alternative_service1, 1.0)); + AlternativeServiceInfo(www_alternative_service1, 1.0, expiration1)); AlternativeService www_alternative_service2(NPN_HTTP_2, "www.google.com", 1234); + base::Time expiration2; + ASSERT_TRUE(base::Time::FromUTCString("2036-12-31 10:00:00", &expiration2)); alternative_service_info_vector.push_back( - AlternativeServiceInfo(www_alternative_service2, 0.7)); + AlternativeServiceInfo(www_alternative_service2, 0.7, expiration2)); http_server_props_manager_->SetAlternativeServices( server_www, alternative_service_info_vector); AlternativeService mail_alternative_service(NPN_SPDY_3_1, "foo.google.com", 444); + base::Time expiration3 = base::Time::Max(); http_server_props_manager_->SetAlternativeService( - server_mail, mail_alternative_service, 0.2); + server_mail, mail_alternative_service, 0.2, expiration3); // Set ServerNetworkStats. ServerNetworkStats stats; @@ -872,13 +882,15 @@ TEST_F(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) { // Verify preferences. const char expected_json[] = "{\"servers\":{\"mail.google.com:80\":{\"alternative_service\":[{" - "\"host\":\"foo.google.com\",\"port\":444,\"probability\":0.2," - "\"protocol_str\":\"npn-spdy/3.1\"}],\"network_stats\":{\"srtt\":42}}," - "\"www.google.com:80\":{\"alternative_service\":[{\"port\":443," - "\"probability\":1.0,\"protocol_str\":\"npn-h2\"}," - "{\"host\":\"www.google.com\",\"port\":1234,\"probability\":0.7," - "\"protocol_str\":\"npn-h2\"}]}},\"supports_quic\":" - "{\"address\":\"127.0.0.1\",\"used_quic\":true},\"version\":3}"; + "\"expiration\":\"9223372036854775807\",\"host\":\"foo.google.com\"," + "\"port\":444,\"probability\":0.2,\"protocol_str\":\"npn-spdy/3.1\"}]," + "\"network_stats\":{\"srtt\":42}},\"www.google.com:80\":{" + "\"alternative_service\":[{\"expiration\":\"13756212000000000\"," + "\"port\":443,\"probability\":1.0,\"protocol_str\":\"npn-h2\"}," + "{\"expiration\":\"13758804000000000\",\"host\":\"www.google.com\"," + "\"port\":1234,\"probability\":0.7,\"protocol_str\":\"npn-h2\"}]}}," + "\"supports_quic\":{\"address\":\"127.0.0.1\",\"used_quic\":true}," + "\"version\":3}"; const base::Value* http_server_properties = pref_service_.GetUserPref(kTestHttpServerProperties); @@ -889,6 +901,95 @@ TEST_F(HttpServerPropertiesManagerTest, UpdateCacheWithPrefs) { EXPECT_EQ(expected_json, preferences_json); } +TEST_F(HttpServerPropertiesManagerTest, AddToAlternativeServiceMap) { + scoped_ptr<base::Value> server_value = base::JSONReader::Read( + "{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"npn-h2\"}," + "{\"port\":123,\"protocol_str\":\"quic\",\"probability\":0.7," + "\"expiration\":\"9223372036854775807\"},{\"host\":\"example.org\"," + "\"port\":1234,\"protocol_str\":\"npn-h2\",\"probability\":0.2," + "\"expiration\":\"13758804000000000\"}]}"); + ASSERT_TRUE(server_value); + base::DictionaryValue* server_dict; + ASSERT_TRUE(server_value->GetAsDictionary(&server_dict)); + + const HostPortPair host_port_pair("example.com", 443); + AlternativeServiceMap alternative_service_map(/*max_size=*/5); + EXPECT_TRUE(http_server_props_manager_->AddToAlternativeServiceMap( + host_port_pair, *server_dict, &alternative_service_map)); + + AlternativeServiceMap::iterator it = + alternative_service_map.Get(host_port_pair); + ASSERT_NE(alternative_service_map.end(), it); + AlternativeServiceInfoVector alternative_service_info_vector = it->second; + ASSERT_EQ(3u, alternative_service_info_vector.size()); + + EXPECT_EQ(NPN_HTTP_2, + alternative_service_info_vector[0].alternative_service.protocol); + EXPECT_EQ("", alternative_service_info_vector[0].alternative_service.host); + EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service.port); + // Probability defaults to 1.0. + EXPECT_DOUBLE_EQ(1.0, alternative_service_info_vector[0].probability); + // Expiration defaults to one day from now, testing with tolerance. + const base::Time now = base::Time::Now(); + const base::Time expiration = alternative_service_info_vector[0].expiration; + EXPECT_LE(now + base::TimeDelta::FromHours(23), expiration); + EXPECT_GE(now + base::TimeDelta::FromDays(1), expiration); + + EXPECT_EQ(QUIC, + alternative_service_info_vector[1].alternative_service.protocol); + EXPECT_EQ("", alternative_service_info_vector[1].alternative_service.host); + EXPECT_EQ(123, alternative_service_info_vector[1].alternative_service.port); + EXPECT_DOUBLE_EQ(0.7, alternative_service_info_vector[1].probability); + // numeric_limits<int64>::max() represents base::Time::Max(). + EXPECT_EQ(base::Time::Max(), alternative_service_info_vector[1].expiration); + + EXPECT_EQ(NPN_HTTP_2, + alternative_service_info_vector[2].alternative_service.protocol); + EXPECT_EQ("example.org", + alternative_service_info_vector[2].alternative_service.host); + EXPECT_EQ(1234, alternative_service_info_vector[2].alternative_service.port); + EXPECT_DOUBLE_EQ(0.2, alternative_service_info_vector[2].probability); + base::Time expected_expiration; + ASSERT_TRUE( + base::Time::FromUTCString("2036-12-31 10:00:00", &expected_expiration)); + EXPECT_EQ(expected_expiration, alternative_service_info_vector[2].expiration); +} + +// Early release 46 Dev and Canary builds serialized alternative service +// expiration as double. Test that they are properly parsed. +// TODO(bnc) Remove this test around 2015-10-01, +// and remove corresponding FRIEND macro from header file. +TEST_F(HttpServerPropertiesManagerTest, AlternativeServiceExpirationDouble) { + scoped_ptr<base::Value> server_value = base::JSONReader::Read( + "{\"alternative_service\":[{\"port\":443,\"protocol_str\":\"npn-h2\"," + "\"expiration\":1234567890.0}]}"); + ASSERT_TRUE(server_value); + base::DictionaryValue* server_dict; + ASSERT_TRUE(server_value->GetAsDictionary(&server_dict)); + + const HostPortPair host_port_pair("example.com", 443); + AlternativeServiceMap alternative_service_map(/*max_size=*/5); + EXPECT_TRUE(http_server_props_manager_->AddToAlternativeServiceMap( + host_port_pair, *server_dict, &alternative_service_map)); + + AlternativeServiceMap::iterator it = + alternative_service_map.Get(host_port_pair); + ASSERT_NE(alternative_service_map.end(), it); + AlternativeServiceInfoVector alternative_service_info_vector = it->second; + ASSERT_EQ(1u, alternative_service_info_vector.size()); + + EXPECT_EQ(NPN_HTTP_2, + alternative_service_info_vector[0].alternative_service.protocol); + EXPECT_EQ("", alternative_service_info_vector[0].alternative_service.host); + EXPECT_EQ(443, alternative_service_info_vector[0].alternative_service.port); + // Probability defaults to 1.0. + EXPECT_DOUBLE_EQ(1.0, alternative_service_info_vector[0].probability); + base::Time expected_expiration; + ASSERT_TRUE( + base::Time::FromUTCString("2009-02-13 23:31:30", &expected_expiration)); + EXPECT_EQ(expected_expiration, alternative_service_info_vector[0].expiration); +} + TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache0) { // Post an update task to the UI thread. http_server_props_manager_->ScheduleUpdateCacheOnPrefThread(); @@ -961,6 +1062,4 @@ TEST_F(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs2) { base::RunLoop().RunUntilIdle(); } -} // namespace - } // namespace net diff --git a/chromium/net/http/http_status_line_validator.cc b/chromium/net/http/http_status_line_validator.cc new file mode 100644 index 00000000000..5b8284cb5a3 --- /dev/null +++ b/chromium/net/http/http_status_line_validator.cc @@ -0,0 +1,136 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_status_line_validator.h" + +#include <vector> + +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" + +namespace net { + +using base::StringPiece; + +HttpStatusLineValidator::StatusLineStatus +HttpStatusLineValidator::ValidateStatusLine(const StringPiece& status_line) { + std::vector<StringPiece> fields = base::SplitStringPiece( + status_line, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + // Permissively split fields, meaning: + // 1) Extra whitespace separating fields ignored + // 2) Extra leading/trailing whitespace removed + std::vector<StringPiece> loose_fields = base::SplitStringPiece( + status_line, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); + + // Fields: HTTP-version status-code reason-phrase + if (fields.empty() || loose_fields.empty()) + return STATUS_LINE_EMPTY; + + StatusLineStatus rv = CheckHttpVersionSyntax(fields[0]); + if (rv != STATUS_LINE_OK) + return rv; + + if (fields.size() < 2) + return STATUS_LINE_MISSING_STATUS_CODE; + + rv = CheckStatusCodeSyntax(fields[1]); + if (rv != STATUS_LINE_OK) + return rv; + + // At this point the field splitting could be wrong, so check for extra + // whitespace/padding on the result code. + // Note that there is no such thing as "extra whitespace" on the + // reason-phrase, since spaces are legal inside it. + if (loose_fields[1] != fields[1]) + return STATUS_LINE_EXCESS_WHITESPACE; + + // An empty reason phrase will cause there to be only two fields in |fields| + // but more than that in |loose_fields|. + if (loose_fields.size() < 3) + return STATUS_LINE_MISSING_REASON_PHRASE; + return CheckReasonPhraseSyntax(fields, 2); +} + +HttpStatusLineValidator::StatusLineStatus +HttpStatusLineValidator::CheckHttpVersionSyntax(const StringPiece& version) { + static const char kProtoName[] = "HTTP"; + static const char kDigits[] = "0123456789"; + if (!base::StartsWith(version, kProtoName, + base::CompareCase::INSENSITIVE_ASCII)) { + return STATUS_LINE_NOT_HTTP; + } + if (!base::StartsWith(version, kProtoName, base::CompareCase::SENSITIVE)) + return STATUS_LINE_HTTP_CASE_MISMATCH; + // Okay, definitely "HTTP" at the start. Now check for the separating slash + // and version number components: + size_t slash = version.find('/'); + if (slash != strlen(kProtoName)) + return STATUS_LINE_HTTP_NO_VERSION; + StringPiece rest = version.substr(slash + 1); + size_t sep = rest.find('.'); + if (sep == StringPiece::npos) { + return STATUS_LINE_INVALID_VERSION; + } + StringPiece major = rest.substr(0, sep); + if (major.length() == 0) + return STATUS_LINE_INVALID_VERSION; + StringPiece minor = rest.substr(sep + 1); + if (minor.length() == 0) + return STATUS_LINE_INVALID_VERSION; + if (major.find_first_not_of(kDigits) != major.npos || + minor.find_first_not_of(kDigits) != minor.npos) { + return STATUS_LINE_INVALID_VERSION; + } + + if (major.length() != 1 || minor.length() != 1) + return STATUS_LINE_MULTI_DIGIT_VERSION; + + // It is now known that version looks like: + // HTTP/x.y + // For single digits x and y. + // Check that x == '1' and y == '0' or '1' + if (major[0] != '1' || (minor[0] != '0' && minor[0] != '1')) { + if (major[0] == '0' && minor[0] == '9') + return STATUS_LINE_EXPLICIT_0_9; + else + return STATUS_LINE_UNKNOWN_VERSION; + } + return STATUS_LINE_OK; +} + +HttpStatusLineValidator::StatusLineStatus +HttpStatusLineValidator::CheckStatusCodeSyntax(const StringPiece& status_code) { + if (status_code.length() < 3) + return STATUS_LINE_INVALID_STATUS_CODE; + if (!isdigit(status_code[0]) || !isdigit(status_code[1]) || + !isdigit(status_code[2])) { + return STATUS_LINE_INVALID_STATUS_CODE; + } + if (status_code.length() > 3) + return STATUS_LINE_STATUS_CODE_TRAILING; + // The only valid codes are 1xx through 5xx, see RFC 7231 S6 + if (status_code[0] < '1' || status_code[0] > '5') + return STATUS_LINE_RESERVED_STATUS_CODE; + return STATUS_LINE_OK; +} + +HttpStatusLineValidator::StatusLineStatus +HttpStatusLineValidator::CheckReasonPhraseSyntax( + const std::vector<StringPiece>& fields, + size_t start_index) { + for (size_t i = start_index; i < fields.size(); ++i) { + for (size_t j = 0; j < fields[i].length(); ++j) { + // VCHAR is any "visible" ASCII character, meaning any non-control + // character, so >= ' ' but not DEL (\x7f). + // obs-text is any character between \x80 and \xff. + // HTAB is \t, SP is ' ' + char c = fields[i][j]; + if (c == '\x7f' || (c < ' ' && c != '\t')) + return STATUS_LINE_REASON_DISALLOWED_CHARACTER; + } + } + return STATUS_LINE_OK; +} + +} // namespace net diff --git a/chromium/net/http/http_status_line_validator.h b/chromium/net/http/http_status_line_validator.h new file mode 100644 index 00000000000..1bfa69f878d --- /dev/null +++ b/chromium/net/http/http_status_line_validator.h @@ -0,0 +1,86 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_HTTP_HTTP_STATUS_LINE_VALIDATOR_H_ +#define NET_HTTP_HTTP_STATUS_LINE_VALIDATOR_H_ + +#include <vector> + +#include "base/basictypes.h" +#include "base/strings/string_piece.h" +#include "net/base/net_export.h" + +namespace net { + +class HttpStatusLineValidator { + public: + // RFC 7230 S3.1.2: + // status-line = HTTP-version SP status-code SP reason-phrase CRLF + // status-code = 3DIGIT + // reason-phrase = *( HTAB / SP / VCHAR / obs-text ) + // And from RFC 7230 S2.6: + // HTTP-version = HTTP-name "/" DIGIT "." DIGIT + // HTTP-name = "\x48\x54\x54\x50" ; ie, "HTTP" in uppercase + enum StatusLineStatus { + // No violations found. + STATUS_LINE_OK = 0, + // "" + STATUS_LINE_EMPTY = 1, + // "xyzzy" + STATUS_LINE_NOT_HTTP = 2, + // "HtTp/1.1 ..." + STATUS_LINE_HTTP_CASE_MISMATCH = 3, + // "HTTP" or "HTTP/" + STATUS_LINE_HTTP_NO_VERSION = 4, + // "HTTP/abc" or "HTTP/1" or "HTTP/1." + STATUS_LINE_INVALID_VERSION = 5, + // "HTTP/1.234 ..." + STATUS_LINE_MULTI_DIGIT_VERSION = 6, + // "HTTP/3.0 ..." + STATUS_LINE_UNKNOWN_VERSION = 7, + // "HTTP/0.9 ..." + STATUS_LINE_EXPLICIT_0_9 = 8, + // "HTTP/1.1" + STATUS_LINE_MISSING_STATUS_CODE = 9, + // "HTTP/1.1 abc" + STATUS_LINE_INVALID_STATUS_CODE = 10, + // "HTTP/1.1 123a" + STATUS_LINE_STATUS_CODE_TRAILING = 11, + // "HTTP/1.1 404", note that "HTTP/1.1 404 " is a valid empty reason phrase + STATUS_LINE_MISSING_REASON_PHRASE = 12, + // "HTTP/1.1 200 \x01" + STATUS_LINE_REASON_DISALLOWED_CHARACTER = 13, + // "HTTP/1.1 200 OK" + STATUS_LINE_EXCESS_WHITESPACE = 14, + // "HTTP/1.1 600 OK" + STATUS_LINE_RESERVED_STATUS_CODE = 15, + + STATUS_LINE_MAX + }; + + // Checks for violations of the RFC 7230 S3.1.2 status-line grammar, and + // returns the first violation found, or STATUS_LINE_OK if the status line + // looks conforming. + static StatusLineStatus NET_EXPORT_PRIVATE ValidateStatusLine( + const base::StringPiece& status_line); + + private: + static StatusLineStatus CheckHttpVersionSyntax( + const base::StringPiece& version); + static StatusLineStatus CheckStatusCodeSyntax( + const base::StringPiece& status_code); + // Checks |fields| against the reason-phrase syntax in RFC 7230 S3.1.2, ie: + // reason-phrase = *( HTAB / SP / VCHAR / obs-text ) + // Note that the HTTP stream parser ignores the reason-phrase entirely, so + // this check is needlessly pedantic. + static StatusLineStatus CheckReasonPhraseSyntax( + const std::vector<base::StringPiece>& fields, + size_t start_index); + + DISALLOW_IMPLICIT_CONSTRUCTORS(HttpStatusLineValidator); +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_STATUS_LINE_VALIDATOR_H_ diff --git a/chromium/net/http/http_status_line_validator_unittest.cc b/chromium/net/http/http_status_line_validator_unittest.cc new file mode 100644 index 00000000000..43a8bf2360f --- /dev/null +++ b/chromium/net/http/http_status_line_validator_unittest.cc @@ -0,0 +1,88 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/http/http_status_line_validator.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { +namespace { + +using Status = HttpStatusLineValidator::StatusLineStatus; + +struct ValidatorTestData { + const char* name; + const char* status_line; + const Status expected_status; +}; + +class ValidatorTest : public ::testing::Test, + public ::testing::WithParamInterface<ValidatorTestData> { + public: + ValidatorTest() {} + ~ValidatorTest() override {} +}; + +std::string TestName(testing::TestParamInfo<ValidatorTestData> info) { + return info.param.name; +} + +TEST_P(ValidatorTest, Validate) { + const ValidatorTestData test = GetParam(); + + EXPECT_EQ(HttpStatusLineValidator::ValidateStatusLine(test.status_line), + test.expected_status); +} + +const ValidatorTestData validator_tests[] = { + {"Http10_Ok", "HTTP/1.0 200 OK", Status::STATUS_LINE_OK}, + {"Http11_Ok", "HTTP/1.1 200 OK", Status::STATUS_LINE_OK}, + {"Empty", "", Status::STATUS_LINE_EMPTY}, + {"NotHttp", "xyzzy", Status::STATUS_LINE_NOT_HTTP}, + {"CaseMismatch", "HtTp/1.1 200 OK", Status::STATUS_LINE_HTTP_CASE_MISMATCH}, + {"NoVersion", "HTTP 200 OK", Status::STATUS_LINE_HTTP_NO_VERSION}, + {"InvalidVersion_0", "HTTP/a.b 200 OK", + Status::STATUS_LINE_INVALID_VERSION}, + {"InvalidVersion_1", "HTTP/1.a 200 OK", + Status::STATUS_LINE_INVALID_VERSION}, + {"InvalidVersion_2", "HTTP/a.1 200 OK", + Status::STATUS_LINE_INVALID_VERSION}, + {"InvalidVersion_3", "HTTP/1 200 OK", Status::STATUS_LINE_INVALID_VERSION}, + {"InvalidVersion_4", "HTTP/1. 200 OK", Status::STATUS_LINE_INVALID_VERSION}, + {"MultiDigit_0", "HTTP/10.0 200 OK", + Status::STATUS_LINE_MULTI_DIGIT_VERSION}, + {"MultiDigit_1", "HTTP/1.00 200 OK", + Status::STATUS_LINE_MULTI_DIGIT_VERSION}, + {"UnknownVersion_0", "HTTP/1.2 200 OK", + Status::STATUS_LINE_UNKNOWN_VERSION}, + {"UnknownVersion_1", "HTTP/2.0 200 OK", + Status::STATUS_LINE_UNKNOWN_VERSION}, + {"Explicit09", "HTTP/0.9 200 OK", Status::STATUS_LINE_EXPLICIT_0_9}, + {"MissingStatusCode", "HTTP/1.0", Status::STATUS_LINE_MISSING_STATUS_CODE}, + {"InvalidStatusCode_0", "HTTP/1.0 abc OK", + Status::STATUS_LINE_INVALID_STATUS_CODE}, + {"InvalidStatusCode_1", "HTTP/1.0 17 OK", + Status::STATUS_LINE_INVALID_STATUS_CODE}, + {"StatusCodeTrailing", "HTTP/1.0 200a OK", + Status::STATUS_LINE_STATUS_CODE_TRAILING}, + {"MissingReasonPhrase", "HTTP/1.0 200", + Status::STATUS_LINE_MISSING_REASON_PHRASE}, + {"EmptyReasonPhrase_Ok", "HTTP/1.0 200 ", Status::STATUS_LINE_OK}, + {"ReasonDisallowedCharacter", "HTTP/1.0 200 OK\x01", + Status::STATUS_LINE_REASON_DISALLOWED_CHARACTER}, + {"ExcessWhitespace", "HTTP/1.0 200 OK", + Status::STATUS_LINE_EXCESS_WHITESPACE}, + {"ReasonWhitespace_Ok", "HTTP/1.0 200 OK", Status::STATUS_LINE_OK}, + {"ReservedStatusCode_0", "HTTP/1.0 099 OK", + Status::STATUS_LINE_RESERVED_STATUS_CODE}, + {"ReservedStatusCode_1", "HTTP/1.0 600 OK", + Status::STATUS_LINE_RESERVED_STATUS_CODE}}; + +INSTANTIATE_TEST_CASE_P(HttpStatusLineValidator, + ValidatorTest, + testing::ValuesIn(validator_tests), + TestName); + +} // namespace +} // namespace net diff --git a/chromium/net/http/http_stream.h b/chromium/net/http/http_stream.h index 3e8703d1b23..1febd11ae95 100644 --- a/chromium/net/http/http_stream.h +++ b/chromium/net/http/http_stream.h @@ -11,6 +11,8 @@ #ifndef NET_HTTP_HTTP_STREAM_H_ #define NET_HTTP_HTTP_STREAM_H_ +#include <stdint.h> + #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "net/base/completion_callback.h" @@ -26,6 +28,7 @@ class HttpRequestHeaders; struct HttpRequestInfo; class HttpResponseInfo; class IOBuffer; +class IPEndPoint; struct LoadTimingInfo; class SSLCertRequestInfo; class SSLInfo; @@ -89,37 +92,37 @@ class NET_EXPORT_PRIVATE HttpStream { // In the case of HTTP, where we re-use the byte-stream (e.g. the connection) // this means we need to close the connection; in the case of SPDY, where the // underlying stream is never reused, it has no effect. - // TODO(mbelshe): We should figure out how to fold the not_reusable flag - // into the stream implementation itself so that the caller - // does not need to pass it at all. We might also be able to - // eliminate the SetConnectionReused() below. + // TODO(mmenke): We should fold the |not_reusable| flag into the stream + // implementation itself so that the caller does not need to + // pass it at all. Ideally we'd be able to remove + // CanReuseConnection() and IsResponseBodyComplete(). + // TODO(mmenke): We should try and merge Drain() into this method as well. virtual void Close(bool not_reusable) = 0; // Indicates if the response body has been completely read. virtual bool IsResponseBodyComplete() const = 0; - // Indicates that the end of the response is detectable. This means that - // the response headers indicate either chunked encoding or content length. - // If neither is sent, the server must close the connection for us to detect - // the end of the response. - // TODO(rch): Rename this method, so that it is clear why it exists - // particularly as it applies to QUIC and SPDY for which the end of the - // response is always findable. - virtual bool CanFindEndOfResponse() const = 0; - // A stream exists on top of a connection. If the connection has been used // to successfully exchange data in the past, error handling for the // stream is done differently. This method returns true if the underlying // connection is reused or has been connected and idle for some time. virtual bool IsConnectionReused() const = 0; + // TODO(mmenke): We should fold this into RenewStreamForAuth(), and make that + // method drain the stream as well, if needed (And return asynchronously). virtual void SetConnectionReused() = 0; - // Checks whether the current state of the underlying connection - // allows it to be reused. - virtual bool IsConnectionReusable() const = 0; + // Checks whether the underlying connection can be reused. The stream's + // connection can be reused if the response headers allow for it, the socket + // is still connected, and the stream exclusively owns the underlying + // connection. SPDY and QUIC streams don't own their own connections, so + // always return false. + virtual bool CanReuseConnection() const = 0; // Get the total number of bytes received from network for this stream. - virtual int64 GetTotalReceivedBytes() const = 0; + virtual int64_t GetTotalReceivedBytes() const = 0; + + // Get the total number of bytes sent over the network for this stream. + virtual int64_t GetTotalSentBytes() const = 0; // Populates the connection establishment part of |load_timing_info|, and // socket ID. |load_timing_info| must have all null times when called. @@ -142,9 +145,10 @@ class NET_EXPORT_PRIVATE HttpStream { // behavior is undefined. virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) = 0; - // HACK(willchan): Really, we should move the HttpResponseDrainer logic into - // the HttpStream implementation. This is just a quick hack. - virtual bool IsSpdyHttpStream() const = 0; + // Gets the remote endpoint of the socket that the HTTP stream is using, if + // any. Returns true and fills in |endpoint| if it is available; returns false + // and does not modify |endpoint| if it is unavailable. + virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) = 0; // In the case of an HTTP error or redirect, flush the response body (usually // a simple error or "this page has moved") so that we can re-use the diff --git a/chromium/net/http/http_stream_factory.cc b/chromium/net/http/http_stream_factory.cc index 2ffe50724c1..1b6e66fccef 100644 --- a/chromium/net/http/http_stream_factory.cc +++ b/chromium/net/http/http_stream_factory.cc @@ -8,9 +8,12 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/time/time.h" #include "net/base/host_mapping_rules.h" #include "net/base/host_port_pair.h" +#include "net/base/port_util.h" #include "net/http/http_network_session.h" +#include "net/spdy/spdy_alt_svc_wire_format.h" #include "url/gurl.h" namespace net { @@ -28,6 +31,44 @@ void HttpStreamFactory::ResetStaticSettingsToInit() { spdy_enabled_ = true; } +void HttpStreamFactory::ProcessAlternativeService( + const base::WeakPtr<HttpServerProperties>& http_server_properties, + base::StringPiece alternative_service_str, + const HostPortPair& http_host_port_pair, + const HttpNetworkSession& session) { + SpdyAltSvcWireFormat::AlternativeServiceVector alternative_service_vector; + if (!SpdyAltSvcWireFormat::ParseHeaderFieldValue( + alternative_service_str, &alternative_service_vector)) { + return; + } + + // Convert SpdyAltSvcWireFormat::AlternativeService entries + // to net::AlternativeServiceInfo. + AlternativeServiceInfoVector alternative_service_info_vector; + for (const SpdyAltSvcWireFormat::AlternativeService& + alternative_service_entry : alternative_service_vector) { + AlternateProtocol protocol = + AlternateProtocolFromString(alternative_service_entry.protocol_id); + if (!IsAlternateProtocolValid(protocol) || + !session.IsProtocolEnabled(protocol) || + !IsPortValid(alternative_service_entry.port)) { + continue; + } + AlternativeService alternative_service(protocol, + alternative_service_entry.host, + alternative_service_entry.port); + base::Time expiration = + base::Time::Now() + + base::TimeDelta::FromSeconds(alternative_service_entry.max_age); + AlternativeServiceInfo alternative_service_info( + alternative_service, alternative_service_entry.p, expiration); + alternative_service_info_vector.push_back(alternative_service_info); + } + + http_server_properties->SetAlternativeServices( + RewriteHost(http_host_port_pair), alternative_service_info_vector); +} + void HttpStreamFactory::ProcessAlternateProtocol( const base::WeakPtr<HttpServerProperties>& http_server_properties, const std::vector<std::string>& alternate_protocol_values, @@ -90,14 +131,10 @@ void HttpStreamFactory::ProcessAlternateProtocol( return; } - HostPortPair host_port(http_host_port_pair); - const HostMappingRules* mapping_rules = GetHostMappingRules(); - if (mapping_rules) - mapping_rules->RewriteHost(&host_port); - http_server_properties->SetAlternativeService( - host_port, AlternativeService(protocol, "", static_cast<uint16>(port)), - probability); + RewriteHost(http_host_port_pair), + AlternativeService(protocol, "", static_cast<uint16>(port)), probability, + base::Time::Now() + base::TimeDelta::FromDays(1)); } GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url, @@ -116,4 +153,11 @@ GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url, HttpStreamFactory::HttpStreamFactory() {} +HostPortPair HttpStreamFactory::RewriteHost(HostPortPair host_port_pair) { + const HostMappingRules* mapping_rules = GetHostMappingRules(); + if (mapping_rules) + mapping_rules->RewriteHost(&host_port_pair); + return host_port_pair; +} + } // namespace net diff --git a/chromium/net/http/http_stream_factory.h b/chromium/net/http/http_stream_factory.h index 114af88c7e2..231271dffe7 100644 --- a/chromium/net/http/http_stream_factory.h +++ b/chromium/net/http/http_stream_factory.h @@ -184,6 +184,12 @@ class NET_EXPORT HttpStreamFactory { public: virtual ~HttpStreamFactory(); + void ProcessAlternativeService( + const base::WeakPtr<HttpServerProperties>& http_server_properties, + base::StringPiece alternative_service_str, + const HostPortPair& http_host_port_pair, + const HttpNetworkSession& session); + void ProcessAlternateProtocol( const base::WeakPtr<HttpServerProperties>& http_server_properties, const std::vector<std::string>& alternate_protocol_values, @@ -219,7 +225,6 @@ class NET_EXPORT HttpStreamFactory { // Requests that enough connections for |num_streams| be opened. virtual void PreconnectStreams(int num_streams, const HttpRequestInfo& info, - RequestPriority priority, const SSLConfig& server_ssl_config, const SSLConfig& proxy_ssl_config) = 0; @@ -244,6 +249,8 @@ class NET_EXPORT HttpStreamFactory { private: static bool spdy_enabled_; + HostPortPair RewriteHost(HostPortPair host_port_pair); + DISALLOW_COPY_AND_ASSIGN(HttpStreamFactory); }; diff --git a/chromium/net/http/http_stream_factory_impl.cc b/chromium/net/http/http_stream_factory_impl.cc index 624bdced9b4..2a8664e51a6 100644 --- a/chromium/net/http/http_stream_factory_impl.cc +++ b/chromium/net/http/http_stream_factory_impl.cc @@ -124,7 +124,6 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestStreamInternal( void HttpStreamFactoryImpl::PreconnectStreams( int num_streams, const HttpRequestInfo& request_info, - RequestPriority priority, const SSLConfig& server_ssl_config, const SSLConfig& proxy_ssl_config) { DCHECK(!for_websockets_); @@ -135,8 +134,13 @@ void HttpStreamFactoryImpl::PreconnectStreams( // TODO(bnc): Pass on multiple alternative services to Job. alternative_service = alternative_service_vector[0]; } + + // Due to how the socket pools handle priorities and idle sockets, only IDLE + // priority currently makes sense for preconnects. The priority for + // preconnects is currently ignored (see RequestSocketsForPool()), but could + // be used at some point for proxy resolution or something. Job* job = - new Job(this, session_, request_info, priority, server_ssl_config, + new Job(this, session_, request_info, IDLE, server_ssl_config, proxy_ssl_config, alternative_service, session_->net_log()); preconnect_job_set_.insert(job); job->Preconnect(num_streams); @@ -148,9 +152,6 @@ const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const { AlternativeServiceVector HttpStreamFactoryImpl::GetAlternativeServicesFor( const GURL& original_url) { - if (!session_->params().use_alternate_protocols) - return AlternativeServiceVector(); - if (original_url.SchemeIs("ftp")) return AlternativeServiceVector(); @@ -162,6 +163,9 @@ AlternativeServiceVector HttpStreamFactoryImpl::GetAlternativeServicesFor( if (alternative_service_vector.empty()) return AlternativeServiceVector(); + const bool enable_different_host = + session_->params().use_alternative_services; + AlternativeServiceVector enabled_alternative_service_vector; for (const AlternativeService& alternative_service : alternative_service_vector) { @@ -172,6 +176,9 @@ AlternativeServiceVector HttpStreamFactoryImpl::GetAlternativeServicesFor( continue; } + if (origin.host() != alternative_service.host && !enable_different_host) + continue; + // Some shared unix systems may have user home directories (like // http://foo.com/~mike) which allow users to emit headers. This is a bad // idea already, but with Alternate-Protocol, it provides the ability for a @@ -204,7 +211,7 @@ AlternativeServiceVector HttpStreamFactoryImpl::GetAlternativeServicesFor( if (session_->quic_stream_factory()->IsQuicDisabled(origin.port())) continue; - if (session_->params().disable_insecure_quic && + if (!session_->params().enable_insecure_quic && !original_url.SchemeIs("https")) { continue; } diff --git a/chromium/net/http/http_stream_factory_impl.h b/chromium/net/http/http_stream_factory_impl.h index 8194f29f378..1ac451dd99e 100644 --- a/chromium/net/http/http_stream_factory_impl.h +++ b/chromium/net/http/http_stream_factory_impl.h @@ -50,7 +50,6 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl : public HttpStreamFactory { void PreconnectStreams(int num_streams, const HttpRequestInfo& info, - RequestPriority priority, const SSLConfig& server_ssl_config, const SSLConfig& proxy_ssl_config) override; const HostMappingRules* GetHostMappingRules() const override; diff --git a/chromium/net/http/http_stream_factory_impl_job.cc b/chromium/net/http/http_stream_factory_impl_job.cc index 004549902df..8955017cded 100644 --- a/chromium/net/http/http_stream_factory_impl_job.cc +++ b/chromium/net/http/http_stream_factory_impl_job.cc @@ -23,6 +23,7 @@ #include "build/build_config.h" #include "net/base/connection_type_histograms.h" #include "net/base/net_util.h" +#include "net/base/port_util.h" #include "net/cert/cert_verifier.h" #include "net/http/http_basic_stream.h" #include "net/http/http_network_session.h" @@ -214,16 +215,18 @@ void HttpStreamFactoryImpl::Job::WaitFor(Job* job) { job->waiting_job_ = this; } -void HttpStreamFactoryImpl::Job::Resume(Job* job) { +void HttpStreamFactoryImpl::Job::Resume(Job* job, + const base::TimeDelta& delay) { DCHECK_EQ(blocking_job_, job); blocking_job_ = NULL; // We know we're blocked if the next_state_ is STATE_WAIT_FOR_JOB_COMPLETE. // Unblock |this|. if (next_state_ == STATE_WAIT_FOR_JOB_COMPLETE) { - base::ThreadTaskRunnerHandle::Get()->PostTask( + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&HttpStreamFactoryImpl::Job::OnIOComplete, - ptr_factory_.GetWeakPtr(), OK)); + ptr_factory_.GetWeakPtr(), OK), + delay); } } @@ -678,7 +681,7 @@ int HttpStreamFactoryImpl::Job::DoStart() { // Don't connect to restricted ports. if (!IsPortAllowedForScheme(server_.port(), request_info_.url.scheme())) { if (waiting_job_) { - waiting_job_->Resume(this); + waiting_job_->Resume(this, base::TimeDelta()); waiting_job_ = NULL; } return ERR_UNSAFE_PORT; @@ -753,7 +756,7 @@ int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) { if (result != OK) { if (waiting_job_) { - waiting_job_->Resume(this); + waiting_job_->Resume(this, base::TimeDelta()); waiting_job_ = NULL; } return result; @@ -859,7 +862,17 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() { // OK, there's no available QUIC session. Let |waiting_job_| resume // if it's paused. if (waiting_job_) { - waiting_job_->Resume(this); + if (rv == ERR_IO_PENDING) { + // Start the |waiting_job_| after the delay returned by + // GetTimeDelayForWaitingJob(). + // + // If QUIC request fails during handshake, then + // DoInitConnectionComplete() will start the |waiting_job_|. + waiting_job_->Resume(this, quic_request_.GetTimeDelayForWaitingJob()); + } else { + // QUIC request has failed, resume the |waiting_job_|. + waiting_job_->Resume(this, base::TimeDelta()); + } waiting_job_ = NULL; } } @@ -895,7 +908,7 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() { // OK, there's no available SPDY session. Let |waiting_job_| resume if it's // paused. if (waiting_job_) { - waiting_job_->Resume(this); + waiting_job_->Resume(this, base::TimeDelta()); waiting_job_ = NULL; } @@ -950,6 +963,10 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() { } int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) { + if (using_quic_ && result < 0 && waiting_job_) { + waiting_job_->Resume(this, base::TimeDelta()); + waiting_job_ = NULL; + } if (IsPreconnecting()) { if (using_quic_) return result; @@ -976,7 +993,7 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) { if (proxy_info_.is_quic() && using_quic_) { if (result == ERR_QUIC_PROTOCOL_ERROR || - result == ERR_QUIC_HANDSHAKE_FAILED) { + result == ERR_QUIC_HANDSHAKE_FAILED || result == ERR_MSG_TOO_BIG) { using_quic_ = false; return ReconsiderProxyAfterError(result); } @@ -992,7 +1009,7 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) { // TODO(willchan): Make this a bit more exact. Maybe there are recoverable // errors, such as ignoring certificate errors for Alternate-Protocol. if (result < 0 && waiting_job_) { - waiting_job_->Resume(this); + waiting_job_->Resume(this, base::TimeDelta()); waiting_job_ = NULL; } @@ -1376,6 +1393,7 @@ int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) { // captive portal). case ERR_QUIC_PROTOCOL_ERROR: case ERR_QUIC_HANDSHAKE_FAILED: + case ERR_MSG_TOO_BIG: case ERR_SSL_PROTOCOL_ERROR: break; case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE: @@ -1392,9 +1410,12 @@ int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) { return error; } - if (request_info_.load_flags & LOAD_BYPASS_PROXY) { + // Do not bypass non-QUIC proxy on ERR_MSG_TOO_BIG. + if (!proxy_info_.is_quic() && error == ERR_MSG_TOO_BIG) + return error; + + if (request_info_.load_flags & LOAD_BYPASS_PROXY) return error; - } if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) { session_->ssl_client_auth_cache()->Remove( diff --git a/chromium/net/http/http_stream_factory_impl_job.h b/chromium/net/http/http_stream_factory_impl_job.h index 637e3b1dda5..81b812a6083 100644 --- a/chromium/net/http/http_stream_factory_impl_job.h +++ b/chromium/net/http/http_stream_factory_impl_job.h @@ -8,6 +8,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "net/base/completion_callback.h" #include "net/base/request_priority.h" #include "net/http/http_auth.h" @@ -70,9 +71,10 @@ class HttpStreamFactoryImpl::Job { void WaitFor(Job* job); // Tells |this| that |job| has determined it still needs to continue - // connecting, so allow |this| to continue. If this is not called, then - // |request_| is expected to cancel |this| by deleting it. - void Resume(Job* job); + // connecting, so allow |this| to continue after the specified |delay|. If + // this is not called, then |request_| is expected to cancel |this| by + // deleting it. + void Resume(Job* job, const base::TimeDelta& delay); // Used to detach the Job from |request|. void Orphan(const Request* request); diff --git a/chromium/net/http/http_stream_factory_impl_request_unittest.cc b/chromium/net/http/http_stream_factory_impl_request_unittest.cc index 0e31c1ec05c..7a5483155bf 100644 --- a/chromium/net/http/http_stream_factory_impl_request_unittest.cc +++ b/chromium/net/http/http_stream_factory_impl_request_unittest.cc @@ -4,6 +4,7 @@ #include "net/http/http_stream_factory_impl_request.h" +#include "base/memory/scoped_ptr.h" #include "net/http/http_stream_factory_impl_job.h" #include "net/proxy/proxy_info.h" #include "net/proxy/proxy_service.h" @@ -20,7 +21,6 @@ class HttpStreamFactoryImplRequestTest INSTANTIATE_TEST_CASE_P(NextProto, HttpStreamFactoryImplRequestTest, testing::Values(kProtoSPDY31, - kProtoHTTP2_14, kProtoHTTP2)); namespace { diff --git a/chromium/net/http/http_stream_factory_impl_unittest.cc b/chromium/net/http/http_stream_factory_impl_unittest.cc index f94f8b25605..ed61ebfb0be 100644 --- a/chromium/net/http/http_stream_factory_impl_unittest.cc +++ b/chromium/net/http/http_stream_factory_impl_unittest.cc @@ -4,11 +4,14 @@ #include "net/http/http_stream_factory_impl.h" +#include <stdint.h> + #include <string> #include <vector> #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "net/base/port_util.h" #include "net/base/test_completion_callback.h" #include "net/cert/mock_cert_verifier.h" #include "net/dns/mock_host_resolver.h" @@ -80,17 +83,17 @@ class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase { } void Close(bool not_reusable) override {} bool IsResponseBodyComplete() const override { return false; } - bool CanFindEndOfResponse() const override { return false; } bool IsConnectionReused() const override { return false; } void SetConnectionReused() override {} - bool IsConnectionReusable() const override { return false; } - int64 GetTotalReceivedBytes() const override { return 0; } + bool CanReuseConnection() const override { return false; } + int64_t GetTotalReceivedBytes() const override { return 0; } + int64_t GetTotalSentBytes() const override { return 0; } bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override { return false; } void GetSSLInfo(SSLInfo* ssl_info) override {} void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override {} - bool IsSpdyHttpStream() const override { return false; } + bool GetRemoteEndpoint(IPEndPoint* endpoint) override { return false; } void Drain(HttpNetworkSession* session) override {} void SetPriority(RequestPriority priority) override {} UploadProgress GetUploadProgress() const override { return UploadProgress(); } @@ -300,17 +303,17 @@ void PreconnectHelperForURL(int num_streams, request.url = url; request.load_flags = 0; - session->http_stream_factory()->PreconnectStreams( - num_streams, request, DEFAULT_PRIORITY, ssl_config, ssl_config); + session->http_stream_factory()->PreconnectStreams(num_streams, request, + ssl_config, ssl_config); mock_factory->WaitForPreconnects(); -}; +} void PreconnectHelper(const TestCase& test, HttpNetworkSession* session) { GURL url = test.ssl ? GURL("https://www.google.com") : GURL("http://www.google.com"); PreconnectHelperForURL(test.num_streams, url, session); -}; +} template<typename ParentPool> class CapturePreconnectsSocketPool : public ParentPool { @@ -422,7 +425,6 @@ class HttpStreamFactoryTest : public ::testing::Test, INSTANTIATE_TEST_CASE_P(NextProto, HttpStreamFactoryTest, testing::Values(kProtoSPDY31, - kProtoHTTP2_14, kProtoHTTP2)); TEST_P(HttpStreamFactoryTest, PreconnectDirect) { @@ -613,13 +615,12 @@ TEST_P(HttpStreamFactoryTest, JobNotifiesProxy) { } TEST_P(HttpStreamFactoryTest, UnreachableQuicProxyMarkedAsBad) { - for (int i = 1; i <= 2; i++) { - int mock_error = - i == 1 ? ERR_QUIC_PROTOCOL_ERROR : ERR_QUIC_HANDSHAKE_FAILED; - + const int mock_error[] = {ERR_QUIC_PROTOCOL_ERROR, ERR_QUIC_HANDSHAKE_FAILED, + ERR_MSG_TOO_BIG}; + for (size_t i = 0; i < arraysize(mock_error); ++i) { scoped_ptr<ProxyService> proxy_service; - proxy_service.reset( - ProxyService::CreateFixedFromPacResult("QUIC bad:99; DIRECT")); + proxy_service = + ProxyService::CreateFixedFromPacResult("QUIC bad:99; DIRECT"); HttpNetworkSession::Params params; params.enable_quic = true; @@ -642,7 +643,7 @@ TEST_P(HttpStreamFactoryTest, UnreachableQuicProxyMarkedAsBad) { session->quic_stream_factory()->set_require_confirmation(false); StaticSocketDataProvider socket_data1; - socket_data1.set_connect_data(MockConnect(ASYNC, mock_error)); + socket_data1.set_connect_data(MockConnect(ASYNC, mock_error[i])); socket_factory.AddSocketDataProvider(&socket_data1); // Second connection attempt succeeds. @@ -667,11 +668,11 @@ TEST_P(HttpStreamFactoryTest, UnreachableQuicProxyMarkedAsBad) { // The proxy that failed should now be known to the proxy_service as bad. const ProxyRetryInfoMap& retry_info = session->proxy_service()->proxy_retry_info(); - EXPECT_EQ(1u, retry_info.size()) << i; + EXPECT_EQ(1u, retry_info.size()) << mock_error[i]; EXPECT_TRUE(waiter.used_proxy_info().is_direct()); ProxyRetryInfoMap::const_iterator iter = retry_info.find("quic://bad:99"); - EXPECT_TRUE(iter != retry_info.end()) << i; + EXPECT_TRUE(iter != retry_info.end()) << mock_error[i]; } } @@ -680,8 +681,7 @@ TEST_P(HttpStreamFactoryTest, UnreachableQuicProxyMarkedAsBad) { TEST_P(HttpStreamFactoryTest, QuicLossyProxyMarkedAsBad) { // Checks if a scoped_ptr<ProxyService> proxy_service; - proxy_service.reset( - ProxyService::CreateFixedFromPacResult("QUIC bad:99; DIRECT")); + proxy_service = ProxyService::CreateFixedFromPacResult("QUIC bad:99; DIRECT"); HttpNetworkSession::Params params; params.enable_quic = true; @@ -778,6 +778,7 @@ TEST_P(HttpStreamFactoryTest, PrivacyModeDisablesChannelId) { } namespace { + // Return count of distinct groups in given socket pool. int GetSocketPoolGroupCount(ClientSocketPool* pool) { int count = 0; @@ -789,6 +790,17 @@ int GetSocketPoolGroupCount(ClientSocketPool* pool) { } return count; } + +// Return count of distinct spdy sessions. +int GetSpdySessionCount(HttpNetworkSession* session) { + scoped_ptr<base::Value> value( + session->spdy_session_pool()->SpdySessionPoolInfoToValue()); + base::ListValue* session_list; + if (!value || !value->GetAsList(&session_list)) + return -1; + return session_list->GetSize(); +} + } // namespace TEST_P(HttpStreamFactoryTest, PrivacyModeUsesDifferentSocketPoolGroup) { @@ -903,8 +915,8 @@ TEST_P(HttpStreamFactoryTest, RequestHttpStream) { EXPECT_TRUE(waiter.stream_done()); ASSERT_TRUE(nullptr != waiter.stream()); EXPECT_TRUE(nullptr == waiter.websocket_stream()); - EXPECT_FALSE(waiter.stream()->IsSpdyHttpStream()); + EXPECT_EQ(0, GetSpdySessionCount(session.get())); EXPECT_EQ(1, GetSocketPoolGroupCount( session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); EXPECT_EQ(0, GetSocketPoolGroupCount(session->GetSSLSocketPool( @@ -952,7 +964,8 @@ TEST_P(HttpStreamFactoryTest, RequestHttpStreamOverSSL) { EXPECT_TRUE(waiter.stream_done()); ASSERT_TRUE(nullptr != waiter.stream()); EXPECT_TRUE(nullptr == waiter.websocket_stream()); - EXPECT_FALSE(waiter.stream()->IsSpdyHttpStream()); + + EXPECT_EQ(0, GetSpdySessionCount(session.get())); EXPECT_EQ(1, GetSocketPoolGroupCount( session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); EXPECT_EQ(1, GetSocketPoolGroupCount( @@ -997,7 +1010,8 @@ TEST_P(HttpStreamFactoryTest, RequestHttpStreamOverProxy) { EXPECT_TRUE(waiter.stream_done()); ASSERT_TRUE(nullptr != waiter.stream()); EXPECT_TRUE(nullptr == waiter.websocket_stream()); - EXPECT_FALSE(waiter.stream()->IsSpdyHttpStream()); + + EXPECT_EQ(0, GetSpdySessionCount(session.get())); EXPECT_EQ(0, GetSocketPoolGroupCount( session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); EXPECT_EQ(0, GetSocketPoolGroupCount( @@ -1169,7 +1183,7 @@ TEST_P(HttpStreamFactoryTest, RequestSpdyHttpStream) { SpdySessionDependencies session_deps(GetParam(), ProxyService::CreateDirect()); - MockRead mock_read(ASYNC, OK); + MockRead mock_read(SYNCHRONOUS, ERR_IO_PENDING); SequencedSocketData socket_data(&mock_read, 1, nullptr, 0); socket_data.set_connect_data(MockConnect(ASYNC, OK)); session_deps.socket_factory->AddSocketDataProvider(&socket_data); @@ -1202,7 +1216,8 @@ TEST_P(HttpStreamFactoryTest, RequestSpdyHttpStream) { EXPECT_TRUE(waiter.stream_done()); EXPECT_TRUE(nullptr == waiter.websocket_stream()); ASSERT_TRUE(nullptr != waiter.stream()); - EXPECT_TRUE(waiter.stream()->IsSpdyHttpStream()); + + EXPECT_EQ(1, GetSpdySessionCount(session.get())); EXPECT_EQ(1, GetSocketPoolGroupCount( session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL))); EXPECT_EQ(1, GetSocketPoolGroupCount( @@ -1349,7 +1364,7 @@ TEST_P(HttpStreamFactoryTest, DISABLED_RequestWebSocketSpdyHandshakeStream) { TEST_P(HttpStreamFactoryTest, DISABLED_OrphanedWebSocketStream) { SpdySessionDependencies session_deps(GetParam(), ProxyService::CreateDirect()); - session_deps.use_alternate_protocols = true; + session_deps.use_alternative_services = true; MockRead mock_read(ASYNC, OK); SequencedSocketData socket_data(&mock_read, 1, nullptr, 0); @@ -1374,9 +1389,10 @@ TEST_P(HttpStreamFactoryTest, DISABLED_OrphanedWebSocketStream) { request_info.url = GURL("ws://www.google.com:8888"); request_info.load_flags = 0; + base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); session->http_server_properties()->SetAlternativeService( HostPortPair("www.google.com", 8888), - AlternativeService(NPN_HTTP_2, "www.google.com", 9999), 1.0); + AlternativeService(NPN_HTTP_2, "www.google.com", 9999), 1.0, expiration); SSLConfig ssl_config; StreamRequestWaiter waiter; diff --git a/chromium/net/http/http_stream_parser.cc b/chromium/net/http/http_stream_parser.cc index 3c3b88d76d9..9ddae4853da 100644 --- a/chromium/net/http/http_stream_parser.cc +++ b/chromium/net/http/http_stream_parser.cc @@ -18,6 +18,7 @@ #include "net/http/http_request_headers.h" #include "net/http/http_request_info.h" #include "net/http/http_response_headers.h" +#include "net/http/http_status_line_validator.h" #include "net/http/http_util.h" #include "net/socket/client_socket_handle.h" #include "net/socket/ssl_client_socket.h" @@ -28,10 +29,13 @@ namespace { enum HttpHeaderParserEvent { HEADER_PARSER_INVOKED = 0, - HEADER_HTTP_09_RESPONSE = 1, + // Obsolete: HEADER_HTTP_09_RESPONSE = 1, HEADER_ALLOWED_TRUNCATED_HEADERS = 2, HEADER_SKIPPED_WS_PREFIX = 3, HEADER_SKIPPED_NON_WS_PREFIX = 4, + HEADER_HTTP_09_RESPONSE_OVER_HTTP = 5, + HEADER_HTTP_09_RESPONSE_OVER_SSL = 6, + HEADER_HTTP_09_ON_REUSED_SOCKET = 7, NUM_HEADER_EVENTS }; @@ -198,15 +202,17 @@ HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection, const BoundNetLog& net_log) : io_state_(STATE_NONE), request_(request), - request_headers_(NULL), + request_headers_(nullptr), request_headers_length_(0), read_buf_(read_buffer), read_buf_unused_offset_(0), response_header_start_offset_(-1), received_bytes_(0), + sent_bytes_(0), + response_(nullptr), response_body_length_(-1), response_body_read_(0), - user_read_buf_(NULL), + user_read_buf_(nullptr), user_read_buf_len_(0), connection_(connection), net_log_(net_log), @@ -470,6 +476,7 @@ int HttpStreamParser::DoSendHeadersComplete(int result) { return result; } + sent_bytes_ += result; request_headers_->DidConsume(result); if (request_headers_->BytesRemaining() > 0) { io_state_ = STATE_SEND_HEADERS; @@ -527,6 +534,7 @@ int HttpStreamParser::DoSendBodyComplete(int result) { return result; } + sent_bytes_ += result; request_body_send_buf_->DidConsume(result); io_state_ = STATE_SEND_BODY; @@ -768,37 +776,40 @@ int HttpStreamParser::HandleReadHeaderResult(int result) { if (result == 0) result = ERR_CONNECTION_CLOSED; - if (result < 0 && result != ERR_CONNECTION_CLOSED) { - io_state_ = STATE_DONE; - return result; - } - // If we've used the connection before, then we know it is not a HTTP/0.9 - // response and return ERR_CONNECTION_CLOSED. - if (result == ERR_CONNECTION_CLOSED && read_buf_->offset() == 0 && - connection_->is_reused()) { - io_state_ = STATE_DONE; - return result; - } - - // Record our best estimate of the 'response time' as the time when we read - // the first bytes of the response headers. - if (read_buf_->offset() == 0 && result != ERR_CONNECTION_CLOSED) - response_->response_time = base::Time::Now(); - if (result == ERR_CONNECTION_CLOSED) { - // The connection closed before we detected the end of the headers. + // The connection closed without getting any more data. if (read_buf_->offset() == 0) { - // The connection was closed before any data was sent. Likely an error - // rather than empty HTTP/0.9 response. io_state_ = STATE_DONE; - return ERR_EMPTY_RESPONSE; - } else if (request_->url.SchemeIsCryptographic()) { - // The connection was closed in the middle of the headers. For HTTPS we - // don't parse partial headers. Return a different error code so that we - // know that we shouldn't attempt to retry the request. + // If the connection has not been reused, it may have been a 0-length + // HTTP/0.9 responses, but it was most likely an error, so just return + // ERR_EMPTY_RESPONSE instead. If the connection was reused, just pass + // on the original connection close error, as rather than being an + // empty HTTP/0.9 response it's much more likely the server closed the + // socket before it received the request. + if (!connection_->is_reused()) + return ERR_EMPTY_RESPONSE; + return result; + } + + // Accepting truncated headers over HTTPS is a potential security + // vulnerability, so just return an error in that case. + // + // If response_header_start_offset_ is -1, this may be a < 8 byte HTTP/0.9 + // response. However, accepting such a response over HTTPS would allow a + // MITM to truncate an HTTP/1.x status line to look like a short HTTP/0.9 + // response if the peer put a record boundary at the first 8 bytes. To + // ensure that all response headers received over HTTPS are pristine, treat + // such responses as errors. + // + // TODO(mmenke): Returning ERR_RESPONSE_HEADERS_TRUNCATED when a response + // looks like an HTTP/0.9 response is weird. Should either come up with + // another error code, or, better, disable HTTP/0.9 over HTTPS (and give + // that a new error code). + if (request_->url.SchemeIsCryptographic()) { io_state_ = STATE_DONE; return ERR_RESPONSE_HEADERS_TRUNCATED; } + // Parse things as well as we can and let the caller decide what to do. int end_offset; if (response_header_start_offset_ >= 0) { @@ -808,7 +819,7 @@ int HttpStreamParser::HandleReadHeaderResult(int result) { RecordHeaderParserEvent(HEADER_ALLOWED_TRUNCATED_HEADERS); } else { // The response is apparently using HTTP/0.9. Treat the entire response - // the body. + // as the body. end_offset = 0; } int rv = ParseResponseHeaders(end_offset); @@ -817,6 +828,16 @@ int HttpStreamParser::HandleReadHeaderResult(int result) { return result; } + if (result < 0) { + io_state_ = STATE_DONE; + return result; + } + + // Record our best estimate of the 'response time' as the time when we read + // the first bytes of the response headers. + if (read_buf_->offset() == 0) + response_->response_time = base::Time::Now(); + read_buf_->set_offset(read_buf_->offset() + result); DCHECK_LE(read_buf_->offset(), read_buf_->capacity()); DCHECK_GE(result, 0); @@ -924,38 +945,47 @@ int HttpStreamParser::ParseResponseHeaders(int end_offset) { if (response_header_start_offset_ >= 0) { received_bytes_ += end_offset; - headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( - read_buf_->StartOfBuffer(), end_offset)); + std::string raw_headers = + HttpUtil::AssembleRawHeaders(read_buf_->StartOfBuffer(), end_offset); + ValidateStatusLine( + std::string(read_buf_->StartOfBuffer(), raw_headers.find('\0'))); + headers = new HttpResponseHeaders(raw_headers); } else { // Enough data was read -- there is no status line. headers = new HttpResponseHeaders(std::string("HTTP/0.9 200 OK")); - RecordHeaderParserEvent(HEADER_HTTP_09_RESPONSE); + + if (request_->url.SchemeIsCryptographic()) { + RecordHeaderParserEvent(HEADER_HTTP_09_RESPONSE_OVER_SSL); + } else { + RecordHeaderParserEvent(HEADER_HTTP_09_RESPONSE_OVER_HTTP); + } + if (connection_->is_reused()) + RecordHeaderParserEvent(HEADER_HTTP_09_ON_REUSED_SOCKET); } - // Check for multiple Content-Length headers with no Transfer-Encoding header. - // If they exist, and have distinct values, it's a potential response - // smuggling attack. - if (!headers->HasHeader("Transfer-Encoding")) { - if (HeadersContainMultipleCopiesOfField(*headers.get(), "Content-Length")) + // Check for multiple Content-Length headers when the response is not + // chunked-encoded. If they exist, and have distinct values, it's a potential + // response smuggling attack. + if (!headers->IsChunkEncoded()) { + if (HeadersContainMultipleCopiesOfField(*headers, "Content-Length")) return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH; } // Check for multiple Content-Disposition or Location headers. If they exist, // it's also a potential response smuggling attack. - if (HeadersContainMultipleCopiesOfField(*headers.get(), - "Content-Disposition")) + if (HeadersContainMultipleCopiesOfField(*headers, "Content-Disposition")) return ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION; - if (HeadersContainMultipleCopiesOfField(*headers.get(), "Location")) + if (HeadersContainMultipleCopiesOfField(*headers, "Location")) return ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION; response_->headers = headers; response_->connection_info = HttpResponseInfo::CONNECTION_INFO_HTTP1; - response_->vary_data.Init(*request_, *response_->headers.get()); + response_->vary_data.Init(*request_, *response_->headers); DVLOG(1) << __FUNCTION__ << "()" << " content_length = \"" << response_->headers->GetContentLength() << "\n\"" - << " headers = \"" - << GetResponseHeaderLines(*response_->headers.get()) << "\""; + << " headers = \"" << GetResponseHeaderLines(*response_->headers) + << "\""; return OK; } @@ -1043,7 +1073,11 @@ void HttpStreamParser::SetConnectionReused() { connection_->set_reuse_type(ClientSocketHandle::REUSED_IDLE); } -bool HttpStreamParser::IsConnectionReusable() const { +bool HttpStreamParser::CanReuseConnection() const { + if (!CanFindEndOfResponse()) + return false; + if (!response_->headers || !response_->headers->IsKeepAlive()) + return false; return connection_->socket() && connection_->socket()->IsConnectedAndIdle(); } @@ -1103,4 +1137,11 @@ bool HttpStreamParser::ShouldMergeRequestHeadersAndBody( return false; } +void HttpStreamParser::ValidateStatusLine(const std::string& status_line) { + HttpStatusLineValidator::StatusLineStatus status = + HttpStatusLineValidator::ValidateStatusLine(status_line); + UMA_HISTOGRAM_ENUMERATION("Net.HttpStatusLineStatus", status, + HttpStatusLineValidator::STATUS_LINE_MAX); +} + } // namespace net diff --git a/chromium/net/http/http_stream_parser.h b/chromium/net/http/http_stream_parser.h index ea810196e7d..f56e7ded4c3 100644 --- a/chromium/net/http/http_stream_parser.h +++ b/chromium/net/http/http_stream_parser.h @@ -5,6 +5,8 @@ #ifndef NET_HTTP_HTTP_STREAM_PARSER_H_ #define NET_HTTP_HTTP_STREAM_PARSER_H_ +#include <stdint.h> + #include <string> #include "base/basictypes.h" @@ -73,9 +75,19 @@ class NET_EXPORT_PRIVATE HttpStreamParser { void SetConnectionReused(); - bool IsConnectionReusable() const; + // Returns true if the underlying connection can be reused. + // The connection can be reused if: + // * It's still connected. + // * The response headers indicate the connection can be kept alive. + // * The end of the response can be found. + // + // Note that if response headers have yet to be received, this will return + // false. + bool CanReuseConnection() const; + + int64_t received_bytes() const { return received_bytes_; } - int64 received_bytes() const { return received_bytes_; } + int64_t sent_bytes() const { return sent_bytes_; } void GetSSLInfo(SSLInfo* ssl_info); @@ -169,6 +181,9 @@ class NET_EXPORT_PRIVATE HttpStreamParser { // Examine the parsed headers to try to determine the response body size. void CalculateResponseBodySize(); + // Uploads statistics about status line compliance with RFC 7230. + void ValidateStatusLine(const std::string& status_line); + // Next state of the request, when the current one completes. State io_state_; @@ -196,7 +211,10 @@ class NET_EXPORT_PRIVATE HttpStreamParser { // The amount of received data. If connection is reused then intermediate // value may be bigger than final. - int64 received_bytes_; + int64_t received_bytes_; + + // The amount of sent data. + int64_t sent_bytes_; // The parsed response headers. Owned by the caller of SendRequest. This // cannot be safely accessed after reading the final set of headers, as the diff --git a/chromium/net/http/http_stream_parser_unittest.cc b/chromium/net/http/http_stream_parser_unittest.cc index 76f998a0e97..012960606c1 100644 --- a/chromium/net/http/http_stream_parser_unittest.cc +++ b/chromium/net/http/http_stream_parser_unittest.cc @@ -4,6 +4,8 @@ #include "net/http/http_stream_parser.h" +#include <stdint.h> + #include <algorithm> #include <string> #include <vector> @@ -199,6 +201,208 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_LargeBodyInMemory) { "some header", body.get())); } +TEST(HttpStreamParser, SentBytesNoHeaders) { + MockWrite writes[] = { + MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"), + }; + + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); + scoped_ptr<ClientSocketHandle> socket_handle = + CreateConnectedSocketHandle(&data); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://localhost"); + + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), + BoundNetLog()); + + HttpResponseInfo response; + TestCompletionCallback callback; + EXPECT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", HttpRequestHeaders(), + &response, callback.callback())); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); +} + +TEST(HttpStreamParser, SentBytesWithHeaders) { + MockWrite writes[] = { + MockWrite(SYNCHRONOUS, 0, + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Connection: Keep-Alive\r\n\r\n"), + }; + + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); + scoped_ptr<ClientSocketHandle> socket_handle = + CreateConnectedSocketHandle(&data); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://localhost"); + + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), + BoundNetLog()); + + HttpRequestHeaders headers; + headers.SetHeader("Host", "localhost"); + headers.SetHeader("Connection", "Keep-Alive"); + + HttpResponseInfo response; + TestCompletionCallback callback; + EXPECT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", headers, &response, + callback.callback())); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); +} + +TEST(HttpStreamParser, SentBytesWithHeadersMultiWrite) { + MockWrite writes[] = { + MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"), + MockWrite(SYNCHRONOUS, 1, "Host: localhost\r\n"), + MockWrite(SYNCHRONOUS, 2, "Connection: Keep-Alive\r\n\r\n"), + }; + + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); + scoped_ptr<ClientSocketHandle> socket_handle = + CreateConnectedSocketHandle(&data); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://localhost"); + + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), + BoundNetLog()); + + HttpRequestHeaders headers; + headers.SetHeader("Host", "localhost"); + headers.SetHeader("Connection", "Keep-Alive"); + + HttpResponseInfo response; + TestCompletionCallback callback; + + EXPECT_EQ(OK, parser.SendRequest("GET / HTTP/1.1\r\n", headers, &response, + callback.callback())); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); +} + +TEST(HttpStreamParser, SentBytesWithErrorWritingHeaders) { + MockWrite writes[] = { + MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n"), + MockWrite(SYNCHRONOUS, 1, "Host: localhost\r\n"), + MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET, 2), + }; + + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); + scoped_ptr<ClientSocketHandle> socket_handle = + CreateConnectedSocketHandle(&data); + + HttpRequestInfo request; + request.method = "GET"; + request.url = GURL("http://localhost"); + + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), + BoundNetLog()); + + HttpRequestHeaders headers; + headers.SetHeader("Host", "localhost"); + headers.SetHeader("Connection", "Keep-Alive"); + + HttpResponseInfo response; + TestCompletionCallback callback; + EXPECT_EQ(ERR_CONNECTION_RESET, + parser.SendRequest("GET / HTTP/1.1\r\n", headers, &response, + callback.callback())); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); +} + +TEST(HttpStreamParser, SentBytesPost) { + MockWrite writes[] = { + MockWrite(SYNCHRONOUS, 0, "POST / HTTP/1.1\r\n"), + MockWrite(SYNCHRONOUS, 1, "Content-Length: 12\r\n\r\n"), + MockWrite(SYNCHRONOUS, 2, "hello world!"), + }; + + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); + scoped_ptr<ClientSocketHandle> socket_handle = + CreateConnectedSocketHandle(&data); + + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello world!", 12)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback())); + + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("http://localhost"); + request.upload_data_stream = &upload_data_stream; + + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), + BoundNetLog()); + + HttpRequestHeaders headers; + headers.SetHeader("Content-Length", "12"); + + HttpResponseInfo response; + TestCompletionCallback callback; + EXPECT_EQ(OK, parser.SendRequest("POST / HTTP/1.1\r\n", headers, &response, + callback.callback())); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); +} + +TEST(HttpStreamParser, SentBytesChunkedPostError) { + static const char kChunk[] = "Chunk 1"; + + MockWrite writes[] = { + MockWrite(ASYNC, 0, "POST / HTTP/1.1\r\n"), + MockWrite(ASYNC, 1, "Transfer-Encoding: chunked\r\n\r\n"), + MockWrite(ASYNC, 2, "7\r\nChunk 1\r\n"), + MockWrite(SYNCHRONOUS, ERR_FAILED, 3), + }; + + SequencedSocketData data(nullptr, 0, writes, arraysize(writes)); + scoped_ptr<ClientSocketHandle> socket_handle = + CreateConnectedSocketHandle(&data); + + ChunkedUploadDataStream upload_data_stream(0); + ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback())); + + HttpRequestInfo request; + request.method = "POST"; + request.url = GURL("http://localhost"); + request.upload_data_stream = &upload_data_stream; + + scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer); + HttpStreamParser parser(socket_handle.get(), &request, read_buffer.get(), + BoundNetLog()); + + HttpRequestHeaders headers; + headers.SetHeader("Transfer-Encoding", "chunked"); + + HttpResponseInfo response; + TestCompletionCallback callback; + EXPECT_EQ(ERR_IO_PENDING, parser.SendRequest("POST / HTTP/1.1\r\n", headers, + &response, callback.callback())); + + base::RunLoop().RunUntilIdle(); + upload_data_stream.AppendData(kChunk, arraysize(kChunk) - 1, false); + + base::RunLoop().RunUntilIdle(); + // This write should fail. + upload_data_stream.AppendData(kChunk, arraysize(kChunk) - 1, false); + EXPECT_EQ(ERR_FAILED, callback.WaitForResult()); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); +} + // Test to ensure the HttpStreamParser state machine does not get confused // when sending a request with a chunked body with only one chunk that becomes // available asynchronously. @@ -269,6 +473,9 @@ TEST(HttpStreamParser, AsyncSingleChunkAndAsyncSocket) { parser.ReadResponseBody(body_buffer.get(), kBodySize, callback.callback())); ASSERT_EQ(kBodySize, callback.WaitForResult()); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); + EXPECT_EQ(CountReadBytes(reads, arraysize(reads)), parser.received_bytes()); } // Test to ensure the HttpStreamParser state machine does not get confused @@ -336,6 +543,9 @@ TEST(HttpStreamParser, SyncSingleChunkAndAsyncSocket) { parser.ReadResponseBody(body_buffer.get(), kBodySize, callback.callback())); ASSERT_EQ(kBodySize, callback.WaitForResult()); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); + EXPECT_EQ(CountReadBytes(reads, arraysize(reads)), parser.received_bytes()); } // Test to ensure the HttpStreamParser state machine does not get confused @@ -426,6 +636,9 @@ TEST(HttpStreamParser, AsyncChunkAndAsyncSocketWithMultipleChunks) { parser.ReadResponseBody(body_buffer.get(), kBodySize, callback.callback())); ASSERT_EQ(kBodySize, callback.WaitForResult()); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); + EXPECT_EQ(CountReadBytes(reads, arraysize(reads)), parser.received_bytes()); } // Test to ensure the HttpStreamParser state machine does not get confused @@ -493,6 +706,9 @@ TEST(HttpStreamParser, AsyncEmptyChunkedUpload) { parser.ReadResponseBody(body_buffer.get(), kBodySize, callback.callback())); ASSERT_EQ(kBodySize, callback.WaitForResult()); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); + EXPECT_EQ(CountReadBytes(reads, arraysize(reads)), parser.received_bytes()); } // Test to ensure the HttpStreamParser state machine does not get confused @@ -559,6 +775,9 @@ TEST(HttpStreamParser, SyncEmptyChunkedUpload) { parser.ReadResponseBody(body_buffer.get(), kBodySize, callback.callback())); ASSERT_EQ(kBodySize, callback.WaitForResult()); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); + EXPECT_EQ(CountReadBytes(reads, arraysize(reads)), parser.received_bytes()); } TEST(HttpStreamParser, TruncatedHeaders) { @@ -640,16 +859,21 @@ TEST(HttpStreamParser, TruncatedHeaders) { &response_info, callback.callback())); int rv = parser.ReadResponseHeaders(callback.callback()); + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), + parser.sent_bytes()); if (i == arraysize(reads) - 1) { EXPECT_EQ(OK, rv); EXPECT_TRUE(response_info.headers.get()); + EXPECT_EQ(CountReadBytes(reads[i], 2), parser.received_bytes()); } else { if (protocol == HTTP) { EXPECT_EQ(ERR_CONNECTION_CLOSED, rv); EXPECT_TRUE(response_info.headers.get()); + EXPECT_EQ(CountReadBytes(reads[i], 2), parser.received_bytes()); } else { EXPECT_EQ(ERR_RESPONSE_HEADERS_TRUNCATED, rv); EXPECT_FALSE(response_info.headers.get()); + EXPECT_EQ(0, parser.received_bytes()); } } } @@ -700,6 +924,11 @@ TEST(HttpStreamParser, Websocket101Response) { EXPECT_EQ("a fake websocket frame", base::StringPiece(read_buffer->StartOfBuffer(), read_buffer->capacity())); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); + EXPECT_EQ(CountReadBytes(reads, arraysize(reads)) - + static_cast<int64_t>(strlen("a fake websocket frame")), + parser.received_bytes()); } // Helper class for constructing HttpStreamParser and running GET requests. @@ -1017,7 +1246,7 @@ TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) { const int kBodySize = 1; MockRead reads[] = { MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n"), - MockRead(SYNCHRONOUS, 2, "Content-Length: 1\r\n\r\n"), + MockRead(SYNCHRONOUS, 2, "Content-Length: 1\r\n"), MockRead(SYNCHRONOUS, 3, "Connection: Keep-Alive\r\n\r\n"), MockRead(SYNCHRONOUS, 4, "1"), MockRead(SYNCHRONOUS, 0, 5), // EOF @@ -1051,6 +1280,9 @@ TEST(HttpStreamParser, ReadAfterUnownedObjectsDestroyed) { scoped_refptr<IOBuffer> body_buffer(new IOBuffer(kBodySize)); ASSERT_EQ(kBodySize, parser.ReadResponseBody( body_buffer.get(), kBodySize, callback.callback())); + + EXPECT_EQ(CountWriteBytes(writes, arraysize(writes)), parser.sent_bytes()); + EXPECT_EQ(CountReadBytes(reads, arraysize(reads)), parser.received_bytes()); } } // namespace diff --git a/chromium/net/http/http_transaction.h b/chromium/net/http/http_transaction.h index 6b8ea70cb3b..9ccf3f11cf1 100644 --- a/chromium/net/http/http_transaction.h +++ b/chromium/net/http/http_transaction.h @@ -5,6 +5,8 @@ #ifndef NET_HTTP_HTTP_TRANSACTION_H_ #define NET_HTTP_HTTP_TRANSACTION_H_ +#include <stdint.h> + #include "net/base/completion_callback.h" #include "net/base/load_states.h" #include "net/base/net_export.h" @@ -122,7 +124,10 @@ class NET_EXPORT_PRIVATE HttpTransaction { virtual bool GetFullRequestHeaders(HttpRequestHeaders* headers) const = 0; // Get the number of bytes received from network. - virtual int64 GetTotalReceivedBytes() const = 0; + virtual int64_t GetTotalReceivedBytes() const = 0; + + // Get the number of bytes sent over the network. + virtual int64_t GetTotalSentBytes() const = 0; // Called to tell the transaction that we have successfully reached the end // of the stream. This is equivalent to performing an extra Read() at the end @@ -155,6 +160,12 @@ class NET_EXPORT_PRIVATE HttpTransaction { // provide. virtual bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const = 0; + // Gets the remote endpoint of the socket that the transaction's underlying + // stream is using or did use, if any. Returns true and fills in |endpoint| + // if it is available; returns false and leaves |endpoint| unchanged if it is + // unavailable. + virtual bool GetRemoteEndpoint(IPEndPoint* endpoint) const = 0; + // Called when the priority of the parent job changes. virtual void SetPriority(RequestPriority priority) = 0; diff --git a/chromium/net/http/http_transaction_test_util.cc b/chromium/net/http/http_transaction_test_util.cc index 1b2960bb250..628c8fa884f 100644 --- a/chromium/net/http/http_transaction_test_util.cc +++ b/chromium/net/http/http_transaction_test_util.cc @@ -242,9 +242,9 @@ MockNetworkTransaction::MockNetworkTransaction(RequestPriority priority, websocket_handshake_stream_create_helper_(NULL), transaction_factory_(factory->AsWeakPtr()), received_bytes_(0), + sent_bytes_(0), socket_log_id_(NetLog::Source::kInvalidId), - weak_factory_(this) { -} + weak_factory_(this) {} MockNetworkTransaction::~MockNetworkTransaction() {} @@ -325,10 +325,14 @@ bool MockNetworkTransaction::GetFullRequestHeaders( return false; } -int64 MockNetworkTransaction::GetTotalReceivedBytes() const { +int64_t MockNetworkTransaction::GetTotalReceivedBytes() const { return received_bytes_; } +int64_t MockNetworkTransaction::GetTotalSentBytes() const { + return sent_bytes_; +} + void MockNetworkTransaction::DoneReading() { if (transaction_factory_.get()) transaction_factory_->TransactionDoneReading(); @@ -374,6 +378,16 @@ bool MockNetworkTransaction::GetLoadTimingInfo( return true; } +bool MockNetworkTransaction::GetRemoteEndpoint(IPEndPoint* endpoint) const { + IPAddressNumber number; + number.push_back(127); + number.push_back(0); + number.push_back(0); + number.push_back(1); + *endpoint = IPEndPoint(number, 80); + return true; +} + void MockNetworkTransaction::SetPriority(RequestPriority priority) { priority_ = priority; } @@ -383,6 +397,12 @@ void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper( websocket_handshake_stream_create_helper_ = create_helper; } +// static +const int64_t MockNetworkTransaction::kTotalReceivedBytes = 1000; + +// static +const int64_t MockNetworkTransaction::kTotalSentBytes = 100; + int MockNetworkTransaction::StartInternal(const HttpRequestInfo* request, const CompletionCallback& callback, const BoundNetLog& net_log) { @@ -400,10 +420,12 @@ int MockNetworkTransaction::StartInternal(const HttpRequestInfo* request, return ERR_IO_PENDING; } + sent_bytes_ = kTotalSentBytes; + received_bytes_ = kTotalReceivedBytes; + std::string resp_status = t->status; std::string resp_headers = t->response_headers; std::string resp_data = t->data; - received_bytes_ = resp_status.size() + resp_headers.size() + resp_data.size(); if (t->handler) (t->handler)(request, &resp_status, &resp_headers, &resp_data); diff --git a/chromium/net/http/http_transaction_test_util.h b/chromium/net/http/http_transaction_test_util.h index 52b38e845de..61aaeee9b2e 100644 --- a/chromium/net/http/http_transaction_test_util.h +++ b/chromium/net/http/http_transaction_test_util.h @@ -7,6 +7,8 @@ #include "net/http/http_transaction.h" +#include <stdint.h> + #include <string> #include "base/callback.h" @@ -195,7 +197,9 @@ class MockNetworkTransaction bool GetFullRequestHeaders(HttpRequestHeaders* headers) const override; - int64 GetTotalReceivedBytes() const override; + int64_t GetTotalReceivedBytes() const override; + + int64_t GetTotalSentBytes() const override; void DoneReading() override; @@ -209,6 +213,8 @@ class MockNetworkTransaction bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; + bool GetRemoteEndpoint(IPEndPoint* endpoint) const override; + void SetPriority(RequestPriority priority) override; void SetWebSocketHandshakeStreamCreateHelper( @@ -230,6 +236,13 @@ class MockNetworkTransaction RequestPriority priority() const { return priority_; } const HttpRequestInfo* request() const { return request_; } + // Bogus value that will be returned by GetTotalReceivedBytes() if the + // MockNetworkTransaction was started. + static const int64_t kTotalReceivedBytes; + // Bogus value that will be returned by GetTotalSentBytes() if the + // MockNetworkTransaction was started. + static const int64_t kTotalSentBytes; + private: int StartInternal(const HttpRequestInfo* request, const CompletionCallback& callback, @@ -245,7 +258,8 @@ class MockNetworkTransaction RequestPriority priority_; CreateHelper* websocket_handshake_stream_create_helper_; base::WeakPtr<MockNetworkLayer> transaction_factory_; - int64 received_bytes_; + int64_t received_bytes_; + int64_t sent_bytes_; // NetLog ID of the fake / non-existent underlying socket used by the // connection. Requires Start() be passed a BoundNetLog with a real NetLog to diff --git a/chromium/net/http/http_util.cc b/chromium/net/http/http_util.cc index 53693f4bae5..f1e5143e701 100644 --- a/chromium/net/http/http_util.cc +++ b/chromium/net/http/http_util.cc @@ -43,40 +43,6 @@ static size_t FindStringEnd(const std::string& line, size_t start, char delim) { // HttpUtil ------------------------------------------------------------------- // static -size_t HttpUtil::FindDelimiter(const std::string& line, - size_t search_start, - char delimiter) { - do { - // search_start points to the spot from which we should start looking - // for the delimiter. - const char delim_str[] = { delimiter, '"', '\'', '\0' }; - size_t cur_delim_pos = line.find_first_of(delim_str, search_start); - if (cur_delim_pos == std::string::npos) - return line.length(); - - char ch = line[cur_delim_pos]; - if (ch == delimiter) { - // Found delimiter - return cur_delim_pos; - } - - // We hit the start of a quoted string. Look for its end. - search_start = FindStringEnd(line, cur_delim_pos, ch); - if (search_start == line.length()) - return search_start; - - ++search_start; - - // search_start now points to the first char after the end of the - // string, so just go back to the top of the loop and look for - // |delimiter| again. - } while (true); - - NOTREACHED(); - return line.length(); -} - -// static void HttpUtil::ParseContentType(const std::string& content_type_str, std::string* mime_type, std::string* charset, @@ -118,14 +84,15 @@ void HttpUtil::ParseContentType(const std::string& content_type_str, DCHECK(param_value_begin <= tokenizer.token_end()); TrimLWS(¶m_value_begin, ¶m_value_end); - if (base::LowerCaseEqualsASCII(param_name_begin, param_name_end, - "charset")) { + if (base::LowerCaseEqualsASCII( + base::StringPiece(param_name_begin, param_name_end), "charset")) { // TODO(abarth): Refactor this function to consistently use iterators. charset_val = param_value_begin - begin; charset_end = param_value_end - begin; type_has_charset = true; - } else if (base::LowerCaseEqualsASCII(param_name_begin, param_name_end, - "boundary")) { + } else if (base::LowerCaseEqualsASCII( + base::StringPiece(param_name_begin, param_name_end), + "boundary")) { if (boundary) boundary->assign(param_value_begin, param_value_end); } @@ -162,16 +129,17 @@ void HttpUtil::ParseContentType(const std::string& content_type_str, content_type_str.find_first_of('/') != std::string::npos) { // Common case here is that mime_type is empty bool eq = !mime_type->empty() && - base::LowerCaseEqualsASCII(begin + type_val, begin + type_end, - mime_type->data()); + base::LowerCaseEqualsASCII( + base::StringPiece(begin + type_val, begin + type_end), + mime_type->data()); if (!eq) { - mime_type->assign(begin + type_val, begin + type_end); - base::StringToLowerASCII(mime_type); + *mime_type = base::ToLowerASCII( + base::StringPiece(begin + type_val, begin + type_end)); } if ((!eq && *had_charset) || type_has_charset) { *had_charset = true; - charset->assign(begin + charset_val, begin + charset_end); - base::StringToLowerASCII(charset); + *charset = base::ToLowerASCII( + base::StringPiece(begin + charset_val, begin + charset_end)); } } } @@ -220,7 +188,8 @@ bool HttpUtil::ParseRangeHeader(const std::string& ranges_specifier, TrimLWS(&bytes_unit_begin, &bytes_unit_end); // "bytes" unit identifier is not found. - if (!base::LowerCaseEqualsASCII(bytes_unit_begin, bytes_unit_end, "bytes")) + if (!base::LowerCaseEqualsASCII( + base::StringPiece(bytes_unit_begin, bytes_unit_end), "bytes")) return false; ValuesIterator byte_range_set_iterator(byte_range_set_begin, @@ -352,7 +321,7 @@ const char* const kForbiddenHeaderFields[] = { // static bool HttpUtil::IsSafeHeader(const std::string& name) { - std::string lower_name(base::StringToLowerASCII(name)); + std::string lower_name(base::ToLowerASCII(name)); if (base::StartsWith(lower_name, "proxy-", base::CompareCase::SENSITIVE) || base::StartsWith(lower_name, "sec-", base::CompareCase::SENSITIVE)) return false; @@ -386,8 +355,9 @@ std::string HttpUtil::StripHeaders(const std::string& headers, while (it.GetNext()) { bool should_remove = false; for (size_t i = 0; i < headers_to_remove_len; ++i) { - if (base::LowerCaseEqualsASCII(it.name_begin(), it.name_end(), - headers_to_remove[i])) { + if (base::LowerCaseEqualsASCII( + base::StringPiece(it.name_begin(), it.name_end()), + headers_to_remove[i])) { should_remove = true; break; } @@ -422,7 +392,7 @@ bool HttpUtil::IsNonCoalescingHeader(std::string::const_iterator name_begin, "strict-transport-security" }; for (size_t i = 0; i < arraysize(kNonCoalescingHeaders); ++i) { - if (base::LowerCaseEqualsASCII(name_begin, name_end, + if (base::LowerCaseEqualsASCII(base::StringPiece(name_begin, name_end), kNonCoalescingHeaders[i])) return true; } @@ -537,7 +507,8 @@ int HttpUtil::LocateStartOfStatusLine(const char* buf, int buf_len) { if (buf_len >= http_len) { int i_max = std::min(buf_len - http_len, slop); for (int i = 0; i <= i_max; ++i) { - if (base::LowerCaseEqualsASCII(buf + i, buf + i + http_len, "http")) + if (base::LowerCaseEqualsASCII(base::StringPiece(buf + i, http_len), + "http")) return i; } } @@ -753,7 +724,7 @@ bool HttpUtil::HasStrongValidators(HttpVersion version, std::string::const_iterator i = etag_header.begin(); std::string::const_iterator j = etag_header.begin() + slash; TrimLWS(&i, &j); - if (!base::LowerCaseEqualsASCII(i, j, "w")) + if (!base::LowerCaseEqualsASCII(base::StringPiece(i, j), "w")) return true; } @@ -850,11 +821,12 @@ bool HttpUtil::HeadersIterator::GetNext() { bool HttpUtil::HeadersIterator::AdvanceTo(const char* name) { DCHECK(name != NULL); - DCHECK_EQ(0, base::StringToLowerASCII<std::string>(name).compare(name)) + DCHECK_EQ(0, base::ToLowerASCII(name).compare(name)) << "the header name must be in all lower case"; while (GetNext()) { - if (base::LowerCaseEqualsASCII(name_begin_, name_end_, name)) { + if (base::LowerCaseEqualsASCII(base::StringPiece(name_begin_, name_end_), + name)) { return true; } } @@ -889,15 +861,22 @@ bool HttpUtil::ValuesIterator::GetNext() { HttpUtil::NameValuePairsIterator::NameValuePairsIterator( std::string::const_iterator begin, std::string::const_iterator end, - char delimiter) + char delimiter, + OptionalValues optional_values) : props_(begin, end, delimiter), valid_(true), name_begin_(end), name_end_(end), value_begin_(end), value_end_(end), - value_is_quoted_(false) { -} + value_is_quoted_(false), + values_optional_(optional_values == VALUES_OPTIONAL) {} + +HttpUtil::NameValuePairsIterator::NameValuePairsIterator( + std::string::const_iterator begin, + std::string::const_iterator end, + char delimiter) + : NameValuePairsIterator(begin, end, delimiter, VALUES_NOT_OPTIONAL) {} HttpUtil::NameValuePairsIterator::~NameValuePairsIterator() {} @@ -907,7 +886,7 @@ HttpUtil::NameValuePairsIterator::~NameValuePairsIterator() {} // name='\'value\'' // name=value // name = value -// name= +// name (if values_optional_ is true) // Due to buggy implementations found in some embedded devices, we also // accept values with missing close quotemark (http://crbug.com/39836): // name="value @@ -922,28 +901,34 @@ bool HttpUtil::NameValuePairsIterator::GetNext() { // Scan for the equals sign. std::string::const_iterator equals = std::find(value_begin_, value_end_, '='); - if (equals == value_end_ || equals == value_begin_) - return valid_ = false; // Malformed, no equals sign - - // Verify that the equals sign we found wasn't inside of quote marks. - for (std::string::const_iterator it = value_begin_; it != equals; ++it) { - if (HttpUtil::IsQuote(*it)) - return valid_ = false; // Malformed, quote appears before equals sign + if (equals == value_begin_) + return valid_ = false; // Malformed, no name + if (equals == value_end_ && !values_optional_) + return valid_ = false; // Malformed, no equals sign and values are required + + // If an equals sign was found, verify that it wasn't inside of quote marks. + if (equals != value_end_) { + for (std::string::const_iterator it = value_begin_; it != equals; ++it) { + if (HttpUtil::IsQuote(*it)) + return valid_ = false; // Malformed, quote appears before equals sign + } } name_begin_ = value_begin_; name_end_ = equals; - value_begin_ = equals + 1; + value_begin_ = (equals == value_end_) ? value_end_ : equals + 1; TrimLWS(&name_begin_, &name_end_); TrimLWS(&value_begin_, &value_end_); value_is_quoted_ = false; unquoted_value_.clear(); - if (value_begin_ == value_end_) - return valid_ = false; // Malformed, value is empty + if (equals != value_end_ && value_begin_ == value_end_) { + // Malformed; value is empty + return valid_ = false; + } - if (HttpUtil::IsQuote(*value_begin_)) { + if (value_begin_ != value_end_ && HttpUtil::IsQuote(*value_begin_)) { // Trim surrounding quotemarks off the value if (*value_begin_ != *(value_end_ - 1) || value_begin_ + 1 == value_end_) { // NOTE: This is not as graceful as it sounds: diff --git a/chromium/net/http/http_util.h b/chromium/net/http/http_util.h index 79a41acd193..1bb3c93f8ab 100644 --- a/chromium/net/http/http_util.h +++ b/chromium/net/http/http_util.h @@ -29,14 +29,6 @@ class NET_EXPORT HttpUtil { // is stripped (username, password, reference). static std::string SpecForRequest(const GURL& url); - // Locates the next occurance of delimiter in line, skipping over quoted - // strings (e.g., commas will not be treated as delimiters if they appear - // within a quoted string). Returns the offset of the found delimiter or - // line.size() if no delimiter was found. - static size_t FindDelimiter(const std::string& line, - size_t search_start, - char delimiter); - // Parses the value of a Content-Type header. The resulting mime_type and // charset values are normalized to lowercase. The mime_type and charset // output values are only modified if the content_type_str contains a mime @@ -323,9 +315,22 @@ class NET_EXPORT HttpUtil { // calls to GetNext() or after the NameValuePairsIterator is destroyed. class NET_EXPORT NameValuePairsIterator { public: + // Whether or not values are optional. VALUES_OPTIONAL allows + // e.g. name1=value1;name2;name3=value3, whereas VALUES_NOT_OPTIONAL + // will treat it as a parse error because name2 does not have a + // corresponding equals sign. + enum OptionalValues { VALUES_OPTIONAL, VALUES_NOT_OPTIONAL }; + + NameValuePairsIterator(std::string::const_iterator begin, + std::string::const_iterator end, + char delimiter, + OptionalValues optional_values); + + // Treats values as not optional by default (VALUES_NOT_OPTIONAL). NameValuePairsIterator(std::string::const_iterator begin, std::string::const_iterator end, char delimiter); + ~NameValuePairsIterator(); // Advances the iterator to the next pair, if any. Returns true if there @@ -353,6 +358,8 @@ class NET_EXPORT HttpUtil { value_end_); } + bool value_is_quoted() const { return value_is_quoted_; } + // The value before unquoting (if any). std::string raw_value() const { return std::string(value_begin_, value_end_); } @@ -373,6 +380,10 @@ class NET_EXPORT HttpUtil { std::string unquoted_value_; bool value_is_quoted_; + + // True if values are required for each name/value pair; false if a + // name is permitted to appear without a corresponding value. + bool values_optional_; }; }; diff --git a/chromium/net/http/http_util_unittest.cc b/chromium/net/http/http_util_unittest.cc index 8d0a219573b..a5c984db66b 100644 --- a/chromium/net/http/http_util_unittest.cc +++ b/chromium/net/http/http_util_unittest.cc @@ -50,8 +50,7 @@ TEST(HttpUtilTest, IsSafeHeader) { for (size_t i = 0; i < arraysize(unsafe_headers); ++i) { EXPECT_FALSE(HttpUtil::IsSafeHeader(unsafe_headers[i])) << unsafe_headers[i]; - EXPECT_FALSE(HttpUtil::IsSafeHeader( - base::StringToUpperASCII(std::string(unsafe_headers[i])))) + EXPECT_FALSE(HttpUtil::IsSafeHeader(base::ToUpperASCII(unsafe_headers[i]))) << unsafe_headers[i]; } static const char* const safe_headers[] = { @@ -96,8 +95,7 @@ TEST(HttpUtilTest, IsSafeHeader) { }; for (size_t i = 0; i < arraysize(safe_headers); ++i) { EXPECT_TRUE(HttpUtil::IsSafeHeader(safe_headers[i])) << safe_headers[i]; - EXPECT_TRUE(HttpUtil::IsSafeHeader( - base::StringToUpperASCII(std::string(safe_headers[i])))) + EXPECT_TRUE(HttpUtil::IsSafeHeader(base::ToUpperASCII(safe_headers[i]))) << safe_headers[i]; } } @@ -1092,6 +1090,48 @@ TEST(HttpUtilTest, NameValuePairsIterator) { &parser, false, true, std::string(), std::string())); } +TEST(HttpUtilTest, NameValuePairsIteratorOptionalValues) { + std::string data = "alpha=1; beta;cappa ; delta; e ; f=1"; + // Test that the default parser requires values. + HttpUtil::NameValuePairsIterator default_parser(data.begin(), data.end(), + ';'); + EXPECT_TRUE(default_parser.valid()); + ASSERT_NO_FATAL_FAILURE( + CheckNextNameValuePair(&default_parser, true, true, "alpha", "1")); + ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&default_parser, false, false, + std::string(), std::string())); + + HttpUtil::NameValuePairsIterator values_required_parser( + data.begin(), data.end(), ';', + HttpUtil::NameValuePairsIterator::VALUES_NOT_OPTIONAL); + EXPECT_TRUE(values_required_parser.valid()); + ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&values_required_parser, true, + true, "alpha", "1")); + ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair( + &values_required_parser, false, false, std::string(), std::string())); + + HttpUtil::NameValuePairsIterator parser( + data.begin(), data.end(), ';', + HttpUtil::NameValuePairsIterator::VALUES_OPTIONAL); + EXPECT_TRUE(parser.valid()); + + ASSERT_NO_FATAL_FAILURE( + CheckNextNameValuePair(&parser, true, true, "alpha", "1")); + ASSERT_NO_FATAL_FAILURE( + CheckNextNameValuePair(&parser, true, true, "beta", std::string())); + ASSERT_NO_FATAL_FAILURE( + CheckNextNameValuePair(&parser, true, true, "cappa", std::string())); + ASSERT_NO_FATAL_FAILURE( + CheckNextNameValuePair(&parser, true, true, "delta", std::string())); + ASSERT_NO_FATAL_FAILURE( + CheckNextNameValuePair(&parser, true, true, "e", std::string())); + ASSERT_NO_FATAL_FAILURE( + CheckNextNameValuePair(&parser, true, true, "f", "1")); + ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair(&parser, false, true, + std::string(), std::string())); + EXPECT_TRUE(parser.valid()); +} + TEST(HttpUtilTest, NameValuePairsIteratorIllegalInputs) { ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair("alpha=1", "; beta")); ASSERT_NO_FATAL_FAILURE(CheckInvalidNameValuePair(std::string(), "beta")); diff --git a/chromium/net/http/mock_http_cache.cc b/chromium/net/http/mock_http_cache.cc index d89993ccba3..d939a3d8f96 100644 --- a/chromium/net/http/mock_http_cache.cc +++ b/chromium/net/http/mock_http_cache.cc @@ -55,9 +55,14 @@ struct MockDiskEntry::CallbackInfo { }; MockDiskEntry::MockDiskEntry(const std::string& key) - : key_(key), doomed_(false), sparse_(false), - fail_requests_(false), fail_sparse_requests_(false), busy_(false), - delayed_(false) { + : key_(key), + doomed_(false), + sparse_(false), + fail_requests_(false), + fail_sparse_requests_(false), + busy_(false), + delayed_(false), + cancel_(false) { test_mode_ = GetTestModeForEntry(key); } @@ -148,7 +153,7 @@ int MockDiskEntry::ReadSparseData(int64 offset, DCHECK(!callback.is_null()); if (fail_sparse_requests_) return ERR_NOT_IMPLEMENTED; - if (!sparse_ || busy_) + if (!sparse_ || busy_ || cancel_) return ERR_CACHE_OPERATION_NOT_SUPPORTED; if (offset < 0) return ERR_FAILED; @@ -181,7 +186,7 @@ int MockDiskEntry::WriteSparseData(int64 offset, DCHECK(!callback.is_null()); if (fail_sparse_requests_) return ERR_NOT_IMPLEMENTED; - if (busy_) + if (busy_ || cancel_) return ERR_CACHE_OPERATION_NOT_SUPPORTED; if (!sparse_) { if (data_[1].size()) @@ -215,7 +220,7 @@ int MockDiskEntry::GetAvailableRange(int64 offset, int64* start, const CompletionCallback& callback) { DCHECK(!callback.is_null()); - if (!sparse_ || busy_) + if (!sparse_ || busy_ || cancel_) return ERR_CACHE_OPERATION_NOT_SUPPORTED; if (offset < 0) return ERR_FAILED; @@ -345,7 +350,6 @@ void MockDiskEntry::StoreAndDeliverCallbacks(bool store, } // Statics. -bool MockDiskEntry::cancel_ = false; bool MockDiskEntry::ignore_callbacks_ = false; //----------------------------------------------------------------------------- diff --git a/chromium/net/http/mock_http_cache.h b/chromium/net/http/mock_http_cache.h index c5e5fd9bcf2..632bb3e63c1 100644 --- a/chromium/net/http/mock_http_cache.h +++ b/chromium/net/http/mock_http_cache.h @@ -102,7 +102,7 @@ class MockDiskEntry : public disk_cache::Entry, bool fail_sparse_requests_; bool busy_; bool delayed_; - static bool cancel_; + bool cancel_; static bool ignore_callbacks_; }; diff --git a/chromium/net/http/proxy_connect_redirect_http_stream.cc b/chromium/net/http/proxy_connect_redirect_http_stream.cc index 4e12a327229..d0f69fe7cec 100644 --- a/chromium/net/http/proxy_connect_redirect_http_stream.cc +++ b/chromium/net/http/proxy_connect_redirect_http_stream.cc @@ -58,10 +58,6 @@ bool ProxyConnectRedirectHttpStream::IsResponseBodyComplete() const { return true; } -bool ProxyConnectRedirectHttpStream::CanFindEndOfResponse() const { - return true; -} - bool ProxyConnectRedirectHttpStream::IsConnectionReused() const { NOTREACHED(); return false; @@ -71,12 +67,15 @@ void ProxyConnectRedirectHttpStream::SetConnectionReused() { NOTREACHED(); } -bool ProxyConnectRedirectHttpStream::IsConnectionReusable() const { - NOTREACHED(); +bool ProxyConnectRedirectHttpStream::CanReuseConnection() const { return false; } -int64 ProxyConnectRedirectHttpStream::GetTotalReceivedBytes() const { +int64_t ProxyConnectRedirectHttpStream::GetTotalReceivedBytes() const { + return 0; +} + +int64_t ProxyConnectRedirectHttpStream::GetTotalSentBytes() const { return 0; } @@ -98,7 +97,7 @@ void ProxyConnectRedirectHttpStream::GetSSLCertRequestInfo( NOTREACHED(); } -bool ProxyConnectRedirectHttpStream::IsSpdyHttpStream() const { +bool ProxyConnectRedirectHttpStream::GetRemoteEndpoint(IPEndPoint* endpoint) { NOTREACHED(); return false; } diff --git a/chromium/net/http/proxy_connect_redirect_http_stream.h b/chromium/net/http/proxy_connect_redirect_http_stream.h index 701d18d425a..1b0b6d6b163 100644 --- a/chromium/net/http/proxy_connect_redirect_http_stream.h +++ b/chromium/net/http/proxy_connect_redirect_http_stream.h @@ -5,6 +5,8 @@ #ifndef NET_HTTP_PROXY_CONNECT_REDIRECT_HTTP_STREAM_H_ #define NET_HTTP_PROXY_CONNECT_REDIRECT_HTTP_STREAM_H_ +#include <stdint.h> + #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "net/base/load_timing_info.h" @@ -42,21 +44,19 @@ class ProxyConnectRedirectHttpStream : public HttpStream { bool IsResponseBodyComplete() const override; - // This function may be called. - bool CanFindEndOfResponse() const override; - bool IsConnectionReused() const override; void SetConnectionReused() override; - bool IsConnectionReusable() const override; + bool CanReuseConnection() const override; - int64 GetTotalReceivedBytes() const override; + int64_t GetTotalReceivedBytes() const override; + int64_t GetTotalSentBytes() const override; // This function may be called. bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; void GetSSLInfo(SSLInfo* ssl_info) override; void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override; - bool IsSpdyHttpStream() const override; + bool GetRemoteEndpoint(IPEndPoint* endpoint) override; void Drain(HttpNetworkSession* session) override; // This function may be called. diff --git a/chromium/net/http/transport_security_persister.cc b/chromium/net/http/transport_security_persister.cc index 74a2e56b1ab..78898c327e5 100644 --- a/chromium/net/http/transport_security_persister.cc +++ b/chromium/net/http/transport_security_persister.cc @@ -77,6 +77,7 @@ const char kPinningOnly[] = "pinning-only"; const char kCreated[] = "created"; const char kStsObserved[] = "sts_observed"; const char kPkpObserved[] = "pkp_observed"; +const char kReportUri[] = "report-uri"; std::string LoadState(const base::FilePath& path) { std::string result; @@ -188,10 +189,17 @@ bool TransportSecurityPersister::SerializeData(std::string* output) { serialized->SetDouble(kDynamicSPKIHashesExpiry, pkp_state.expiry.ToDoubleT()); + // TODO(svaldez): Historically, both SHA-1 and SHA-256 hashes were + // accepted in pins. Per spec, only SHA-256 is accepted now, however + // existing serialized pins are still processed. Migrate historical pins + // with SHA-1 hashes properly, either by dropping just the bad hashes or + // the entire pin. See https://crbug.com/448501. if (now < pkp_state.expiry) { serialized->Set(kDynamicSPKIHashes, SPKIHashesToListValue(pkp_state.spki_hashes)); } + + serialized->SetString(kReportUri, pkp_state.report_uri.spec()); } base::JSONWriter::WriteWithOptions( @@ -282,6 +290,13 @@ bool TransportSecurityPersister::Deserialize(const std::string& serialized, sts_state.expiry = base::Time::FromDoubleT(expiry); pkp_state.expiry = base::Time::FromDoubleT(dynamic_spki_hashes_expiry); + // Don't fail if this key is not present. + std::string report_uri_str; + parsed->GetString(kReportUri, &report_uri_str); + GURL report_uri(report_uri_str); + if (report_uri.is_valid()) + pkp_state.report_uri = report_uri; + double sts_observed; double pkp_observed; if (parsed->GetDouble(kStsObserved, &sts_observed)) { diff --git a/chromium/net/http/transport_security_persister_unittest.cc b/chromium/net/http/transport_security_persister_unittest.cc index 53cb2f4b702..0799f5820bd 100644 --- a/chromium/net/http/transport_security_persister_unittest.cc +++ b/chromium/net/http/transport_security_persister_unittest.cc @@ -19,6 +19,8 @@ namespace net { namespace { +const char kReportUri[] = "http://www.example.test/report"; + class TransportSecurityPersisterTest : public testing::Test { public: TransportSecurityPersisterTest() { @@ -86,10 +88,11 @@ TEST_F(TransportSecurityPersisterTest, SerializeData2) { } TEST_F(TransportSecurityPersisterTest, SerializeData3) { + const GURL report_uri(kReportUri); // Add an entry. - HashValue fp1(HASH_VALUE_SHA1); + HashValue fp1(HASH_VALUE_SHA256); memset(fp1.data(), 0, fp1.size()); - HashValue fp2(HASH_VALUE_SHA1); + HashValue fp2(HASH_VALUE_SHA256); memset(fp2.data(), 1, fp2.size()); base::Time expiry = base::Time::Now() + base::TimeDelta::FromSeconds(1000); @@ -99,7 +102,7 @@ TEST_F(TransportSecurityPersisterTest, SerializeData3) { bool include_subdomains = false; state_.AddHSTS("www.example.com", expiry, include_subdomains); state_.AddHPKP("www.example.com", expiry, include_subdomains, - dynamic_spki_hashes); + dynamic_spki_hashes, report_uri); // Add another entry. memset(fp1.data(), 2, fp1.size()); @@ -110,7 +113,7 @@ TEST_F(TransportSecurityPersisterTest, SerializeData3) { dynamic_spki_hashes.push_back(fp2); state_.AddHSTS("www.example.net", expiry, include_subdomains); state_.AddHPKP("www.example.net", expiry, include_subdomains, - dynamic_spki_hashes); + dynamic_spki_hashes, report_uri); // Save a copy of everything. std::set<std::string> sts_saved; @@ -180,21 +183,23 @@ TEST_F(TransportSecurityPersisterTest, SerializeDataOld) { EXPECT_TRUE(dirty); } -TEST_F(TransportSecurityPersisterTest, PublicKeyHashes) { +TEST_F(TransportSecurityPersisterTest, PublicKeyPins) { + const GURL report_uri(kReportUri); TransportSecurityState::PKPState pkp_state; static const char kTestDomain[] = "example.com"; + EXPECT_FALSE(state_.GetDynamicPKPState(kTestDomain, &pkp_state)); HashValueVector hashes; std::string failure_log; EXPECT_FALSE(pkp_state.CheckPublicKeyPins(hashes, &failure_log)); - HashValue sha1(HASH_VALUE_SHA1); - memset(sha1.data(), '1', sha1.size()); - pkp_state.spki_hashes.push_back(sha1); + HashValue sha256(HASH_VALUE_SHA256); + memset(sha256.data(), '1', sha256.size()); + pkp_state.spki_hashes.push_back(sha256); EXPECT_FALSE(pkp_state.CheckPublicKeyPins(hashes, &failure_log)); - hashes.push_back(sha1); + hashes.push_back(sha256); EXPECT_TRUE(pkp_state.CheckPublicKeyPins(hashes, &failure_log)); hashes[0].data()[0] = '2'; @@ -204,8 +209,8 @@ TEST_F(TransportSecurityPersisterTest, PublicKeyHashes) { const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); bool include_subdomains = false; state_.AddHSTS(kTestDomain, expiry, include_subdomains); - state_.AddHPKP(kTestDomain, expiry, include_subdomains, - pkp_state.spki_hashes); + state_.AddHPKP(kTestDomain, expiry, include_subdomains, pkp_state.spki_hashes, + report_uri); std::string serialized; EXPECT_TRUE(persister_->SerializeData(&serialized)); bool dirty; @@ -214,9 +219,10 @@ TEST_F(TransportSecurityPersisterTest, PublicKeyHashes) { TransportSecurityState::PKPState new_pkp_state; EXPECT_TRUE(state_.GetDynamicPKPState(kTestDomain, &new_pkp_state)); EXPECT_EQ(1u, new_pkp_state.spki_hashes.size()); - EXPECT_EQ(sha1.tag, new_pkp_state.spki_hashes[0].tag); - EXPECT_EQ( - 0, memcmp(new_pkp_state.spki_hashes[0].data(), sha1.data(), sha1.size())); + EXPECT_EQ(sha256.tag, new_pkp_state.spki_hashes[0].tag); + EXPECT_EQ(0, memcmp(new_pkp_state.spki_hashes[0].data(), sha256.data(), + sha256.size())); + EXPECT_EQ(report_uri, new_pkp_state.report_uri); } } // namespace diff --git a/chromium/net/http/transport_security_state.cc b/chromium/net/http/transport_security_state.cc index a5f43a016ac..89d467151ba 100644 --- a/chromium/net/http/transport_security_state.cc +++ b/chromium/net/http/transport_security_state.cc @@ -19,6 +19,7 @@ #include "base/base64.h" #include "base/build_time.h" +#include "base/json/json_writer.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/metrics/histogram_macros.h" @@ -26,11 +27,13 @@ #include "base/sha1.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/values.h" #include "crypto/sha2.h" #include "net/base/dns_util.h" +#include "net/base/host_port_pair.h" #include "net/cert/x509_cert_types.h" #include "net/cert/x509_certificate.h" #include "net/http/http_security_headers.h" @@ -47,6 +50,137 @@ namespace { #include "net/http/transport_security_state_static.h" +std::string TimeToISO8601(const base::Time& t) { + base::Time::Exploded exploded; + t.UTCExplode(&exploded); + return base::StringPrintf( + "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month, + exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, + exploded.millisecond); +} + +scoped_ptr<base::ListValue> GetPEMEncodedChainAsList( + const net::X509Certificate* cert_chain) { + if (!cert_chain) + return make_scoped_ptr(new base::ListValue()); + + scoped_ptr<base::ListValue> result(new base::ListValue()); + std::vector<std::string> pem_encoded_chain; + cert_chain->GetPEMEncodedChain(&pem_encoded_chain); + for (const std::string& cert : pem_encoded_chain) + result->Append(make_scoped_ptr(new base::StringValue(cert))); + + return result.Pass(); +} + +bool GetHPKPReport(const HostPortPair& host_port_pair, + const TransportSecurityState::PKPState& pkp_state, + const X509Certificate* served_certificate_chain, + const X509Certificate* validated_certificate_chain, + std::string* serialized_report) { + // TODO(estark): keep track of reports already sent and rate-limit, + // break loops + if (pkp_state.report_uri.is_empty()) + return false; + + base::DictionaryValue report; + base::Time now = base::Time::Now(); + report.SetString("date-time", TimeToISO8601(now)); + report.SetString("hostname", host_port_pair.host()); + report.SetInteger("port", host_port_pair.port()); + report.SetString("effective-expiration-date", + TimeToISO8601(pkp_state.expiry)); + report.SetBoolean("include-subdomains", pkp_state.include_subdomains); + report.SetString("noted-hostname", pkp_state.domain); + + scoped_ptr<base::ListValue> served_certificate_chain_list = + GetPEMEncodedChainAsList(served_certificate_chain); + scoped_ptr<base::ListValue> validated_certificate_chain_list = + GetPEMEncodedChainAsList(validated_certificate_chain); + report.Set("served-certificate-chain", served_certificate_chain_list.Pass()); + report.Set("validated-certificate-chain", + validated_certificate_chain_list.Pass()); + + scoped_ptr<base::ListValue> known_pin_list(new base::ListValue()); + for (const auto& hash_value : pkp_state.spki_hashes) { + std::string known_pin; + + switch (hash_value.tag) { + case HASH_VALUE_SHA1: + known_pin += "pin-sha1="; + break; + case HASH_VALUE_SHA256: + known_pin += "pin-sha256="; + break; + } + + std::string base64_value; + base::Base64Encode( + base::StringPiece(reinterpret_cast<const char*>(hash_value.data()), + hash_value.size()), + &base64_value); + known_pin += "\"" + base64_value + "\""; + + known_pin_list->Append( + scoped_ptr<base::Value>(new base::StringValue(known_pin))); + } + + report.Set("known-pins", known_pin_list.Pass()); + + if (!base::JSONWriter::Write(report, serialized_report)) { + LOG(ERROR) << "Failed to serialize HPKP violation report."; + return false; + } + + return true; +} + +// Do not send a report over HTTPS to the same host that set the +// pin. Such report URIs will result in loops. (A.com has a pinning +// violation which results in a report being sent to A.com, which +// results in a pinning violation which results in a report being sent +// to A.com, etc.) +bool IsReportUriValidForHost(const GURL& report_uri, const std::string& host) { + return (report_uri.host_piece() != host || + !report_uri.SchemeIsCryptographic()); +} + +bool CheckPinsAndMaybeSendReport( + const HostPortPair& host_port_pair, + const TransportSecurityState::PKPState& pkp_state, + const HashValueVector& hashes, + const X509Certificate* served_certificate_chain, + const X509Certificate* validated_certificate_chain, + const TransportSecurityState::PublicKeyPinReportStatus report_status, + TransportSecurityState::ReportSender* report_sender, + std::string* failure_log) { + if (pkp_state.CheckPublicKeyPins(hashes, failure_log)) + return true; + + if (!report_sender || + report_status != TransportSecurityState::ENABLE_PIN_REPORTS || + pkp_state.report_uri.is_empty()) { + return false; + } + + DCHECK(pkp_state.report_uri.is_valid()); + // Report URIs should not be used if they are the same host as the pin + // and are HTTPS, to avoid going into a report-sending loop. + if (!IsReportUriValidForHost(pkp_state.report_uri, host_port_pair.host())) + return false; + + std::string serialized_report; + + if (!GetHPKPReport(host_port_pair, pkp_state, served_certificate_chain, + validated_certificate_chain, &serialized_report)) { + return false; + } + + report_sender->Send(pkp_state.report_uri, serialized_report); + + return false; +} + std::string HashesToBase64String(const HashValueVector& hashes) { std::string str; for (size_t i = 0; i != hashes.size(); ++i) { @@ -313,8 +447,7 @@ bool DecodeHSTSPreloadRaw(const std::string& search_hostname, // |hostname| has already undergone IDN conversion, so should be // entirely A-Labels. The preload data is entirely normalized to // lower case. - base::StringToLowerASCII(&hostname); - + hostname = base::ToLowerASCII(hostname); if (hostname.empty()) { return true; } @@ -473,7 +606,7 @@ bool DecodeHSTSPreload(const std::string& hostname, PreloadResult* out) { } // namespace TransportSecurityState::TransportSecurityState() - : delegate_(NULL), enable_static_pins_(true) { + : delegate_(nullptr), report_sender_(nullptr), enable_static_pins_(true) { // Static pinning is only enabled for official builds to make sure that // others don't end up with pins that cannot be easily updated. #if !defined(OFFICIAL_BUILD) || defined(OS_ANDROID) || defined(OS_IOS) @@ -510,24 +643,28 @@ bool TransportSecurityState::ShouldUpgradeToSSL(const std::string& host) { } bool TransportSecurityState::CheckPublicKeyPins( - const std::string& host, + const HostPortPair& host_port_pair, bool is_issued_by_known_root, const HashValueVector& public_key_hashes, + const X509Certificate* served_certificate_chain, + const X509Certificate* validated_certificate_chain, + const PublicKeyPinReportStatus report_status, std::string* pinning_failure_log) { // Perform pin validation if, and only if, all these conditions obtain: // // * the server's certificate chain chains up to a known root (i.e. not a // user-installed trust anchor); and // * the server actually has public key pins. - if (!is_issued_by_known_root || !HasPublicKeyPins(host)) { + if (!is_issued_by_known_root || !HasPublicKeyPins(host_port_pair.host())) { return true; } - bool pins_are_valid = - CheckPublicKeyPinsImpl(host, public_key_hashes, pinning_failure_log); + bool pins_are_valid = CheckPublicKeyPinsImpl( + host_port_pair, public_key_hashes, served_certificate_chain, + validated_certificate_chain, report_status, pinning_failure_log); if (!pins_are_valid) { LOG(ERROR) << *pinning_failure_log; - ReportUMAOnPinFailure(host); + ReportUMAOnPinFailure(host_port_pair.host()); } UMA_HISTOGRAM_BOOLEAN("Net.PublicKeyPinSuccess", pins_are_valid); @@ -555,6 +692,12 @@ void TransportSecurityState::SetDelegate( delegate_ = delegate; } +void TransportSecurityState::SetReportSender( + TransportSecurityState::ReportSender* report_sender) { + DCHECK(CalledOnValidThread()); + report_sender_ = report_sender; +} + void TransportSecurityState::AddHSTSInternal( const std::string& host, TransportSecurityState::STSState::UpgradeMode upgrade_mode, @@ -575,7 +718,8 @@ void TransportSecurityState::AddHPKPInternal(const std::string& host, const base::Time& last_observed, const base::Time& expiry, bool include_subdomains, - const HashValueVector& hashes) { + const HashValueVector& hashes, + const GURL& report_uri) { DCHECK(CalledOnValidThread()); PKPState pkp_state; @@ -583,6 +727,7 @@ void TransportSecurityState::AddHPKPInternal(const std::string& host, pkp_state.expiry = expiry; pkp_state.include_subdomains = include_subdomains; pkp_state.spki_hashes = hashes; + pkp_state.report_uri = report_uri; EnablePKPHost(host, pkp_state); } @@ -742,14 +887,17 @@ bool TransportSecurityState::AddHPKPHeader(const std::string& host, base::TimeDelta max_age; bool include_subdomains; HashValueVector spki_hashes; + GURL report_uri; + if (!ParseHPKPHeader(value, ssl_info.public_key_hashes, &max_age, - &include_subdomains, &spki_hashes)) { + &include_subdomains, &spki_hashes, &report_uri)) { return false; } // Handle max-age == 0. if (max_age.InSeconds() == 0) spki_hashes.clear(); - AddHPKPInternal(host, now, now + max_age, include_subdomains, spki_hashes); + AddHPKPInternal(host, now, now + max_age, include_subdomains, spki_hashes, + report_uri); return true; } @@ -763,9 +911,48 @@ void TransportSecurityState::AddHSTS(const std::string& host, void TransportSecurityState::AddHPKP(const std::string& host, const base::Time& expiry, bool include_subdomains, - const HashValueVector& hashes) { + const HashValueVector& hashes, + const GURL& report_uri) { DCHECK(CalledOnValidThread()); - AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes); + AddHPKPInternal(host, base::Time::Now(), expiry, include_subdomains, hashes, + report_uri); +} + +bool TransportSecurityState::ProcessHPKPReportOnlyHeader( + const std::string& value, + const HostPortPair& host_port_pair, + const SSLInfo& ssl_info) { + DCHECK(CalledOnValidThread()); + + base::Time now = base::Time::Now(); + bool include_subdomains; + HashValueVector spki_hashes; + GURL report_uri; + std::string unused_failure_log; + + if (!ParseHPKPReportOnlyHeader(value, &include_subdomains, &spki_hashes, + &report_uri) || + !report_uri.is_valid() || report_uri.is_empty()) { + return false; + } + + PKPState pkp_state; + pkp_state.last_observed = now; + pkp_state.expiry = now; + pkp_state.include_subdomains = include_subdomains; + pkp_state.spki_hashes = spki_hashes; + pkp_state.report_uri = report_uri; + pkp_state.domain = DNSDomainToString(CanonicalizeHost(host_port_pair.host())); + + // Only perform pin validation if the cert chains up to a known root. + if (!ssl_info.is_issued_by_known_root) + return true; + + CheckPinsAndMaybeSendReport( + host_port_pair, pkp_state, ssl_info.public_key_hashes, + ssl_info.unverified_cert.get(), ssl_info.cert.get(), ENABLE_PIN_REPORTS, + report_sender_, &unused_failure_log); + return true; } // static @@ -806,21 +993,25 @@ bool TransportSecurityState::IsBuildTimely() { } bool TransportSecurityState::CheckPublicKeyPinsImpl( - const std::string& host, + const HostPortPair& host_port_pair, const HashValueVector& hashes, + const X509Certificate* served_certificate_chain, + const X509Certificate* validated_certificate_chain, + const PublicKeyPinReportStatus report_status, std::string* failure_log) { - PKPState dynamic_state; - if (GetDynamicPKPState(host, &dynamic_state)) - return dynamic_state.CheckPublicKeyPins(hashes, failure_log); - - PKPState static_pkp_state; + PKPState pkp_state; STSState unused; - if (GetStaticDomainState(host, &unused, &static_pkp_state)) - return static_pkp_state.CheckPublicKeyPins(hashes, failure_log); - // HasPublicKeyPins should have returned true in order for this method - // to have been called, so if we fall through to here, it's an error. - return false; + if (!GetDynamicPKPState(host_port_pair.host(), &pkp_state) && + !GetStaticDomainState(host_port_pair.host(), &unused, &pkp_state)) { + // HasPublicKeyPins should have returned true in order for this method + // to have been called, so if we fall through to here, it's an error. + return false; + } + + return CheckPinsAndMaybeSendReport( + host_port_pair, pkp_state, hashes, served_certificate_chain, + validated_certificate_chain, report_status, report_sender_, failure_log); } bool TransportSecurityState::GetStaticDomainState(const std::string& host, @@ -856,6 +1047,9 @@ bool TransportSecurityState::GetStaticDomainState(const std::string& host, return false; const Pinset *pinset = &kPinsets[result.pinset_id]; + if (pinset->report_uri != kNoReportURI) + pkp_state->report_uri = GURL(pinset->report_uri); + if (pinset->accepted_pins) { const char* const* sha1_hash = pinset->accepted_pins; while (*sha1_hash) { diff --git a/chromium/net/http/transport_security_state.h b/chromium/net/http/transport_security_state.h index b441763cb08..d7befb7cfef 100644 --- a/chromium/net/http/transport_security_state.h +++ b/chromium/net/http/transport_security_state.h @@ -5,21 +5,26 @@ #ifndef NET_HTTP_TRANSPORT_SECURITY_STATE_H_ #define NET_HTTP_TRANSPORT_SECURITY_STATE_H_ +#include <stdint.h> + #include <map> #include <string> #include <utility> #include <vector> -#include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/threading/non_thread_safe.h" #include "base/time/time.h" #include "net/base/net_export.h" #include "net/cert/x509_cert_types.h" #include "net/cert/x509_certificate.h" +#include "url/gurl.h" + +class GURL; namespace net { +class HostPortPair; class SSLInfo; // Tracks which hosts have enabled strict transport security and/or public @@ -45,9 +50,6 @@ class NET_EXPORT TransportSecurityState virtual ~Delegate() {} }; - TransportSecurityState(); - ~TransportSecurityState(); - // A STSState describes the strict transport security state (required // upgrade to HTTPS). class NET_EXPORT STSState { @@ -130,6 +132,10 @@ class NET_EXPORT TransportSecurityState // Updated by |GetDynamicPKPState| and |GetStaticDomainState|. std::string domain; + // An optional URI indicating where reports should be sent when this + // pin is violated, or empty when omitted. + GURL report_uri; + // Takes a set of SubjectPublicKeyInfo |hashes| and returns true if: // 1) |bad_static_spki_hashes| does not intersect |hashes|; AND // 2) Both |static_spki_hashes| and |dynamic_spki_hashes| are empty @@ -174,15 +180,35 @@ class NET_EXPORT TransportSecurityState std::map<std::string, PKPState>::const_iterator end_; }; + // An interface for asynchronously sending HPKP violation reports. + class NET_EXPORT ReportSender { + public: + // Sends the given serialized |report| to |report_uri|. + virtual void Send(const GURL& report_uri, const std::string& report) = 0; + + protected: + virtual ~ReportSender() {} + }; + + // Indicates whether or not a public key pin check should send a + // report if a violation is detected. + enum PublicKeyPinReportStatus { ENABLE_PIN_REPORTS, DISABLE_PIN_REPORTS }; + + TransportSecurityState(); + ~TransportSecurityState(); + // These functions search for static and dynamic STS and PKP states, and - // invoke the - // functions of the same name on them. These functions are the primary public - // interface; direct access to STS and PKP states is best left to tests. + // invoke the functions of the same name on them. These functions are the + // primary public interface; direct access to STS and PKP states is best + // left to tests. bool ShouldSSLErrorsBeFatal(const std::string& host); bool ShouldUpgradeToSSL(const std::string& host); - bool CheckPublicKeyPins(const std::string& host, + bool CheckPublicKeyPins(const HostPortPair& host_port_pair, bool is_issued_by_known_root, const HashValueVector& hashes, + const X509Certificate* served_certificate_chain, + const X509Certificate* validated_certificate_chain, + const PublicKeyPinReportStatus report_status, std::string* failure_log); bool HasPublicKeyPins(const std::string& host); @@ -193,6 +219,8 @@ class NET_EXPORT TransportSecurityState // TransportSecurityState. void SetDelegate(Delegate* delegate); + void SetReportSender(ReportSender* report_sender); + // Clears all dynamic data (e.g. HSTS and HPKP data). // // Does NOT persist changes using the Delegate, as this function is only @@ -268,7 +296,16 @@ class NET_EXPORT TransportSecurityState void AddHPKP(const std::string& host, const base::Time& expiry, bool include_subdomains, - const HashValueVector& hashes); + const HashValueVector& hashes, + const GURL& report_uri); + + // Parses |value| as a Public-Key-Pins-Report-Only header value and + // sends a HPKP report for |host_port_pair| if |ssl_info| violates the + // pin. Returns true if |value| parses and includes a valid + // report-uri, and false otherwise. + bool ProcessHPKPReportOnlyHeader(const std::string& value, + const HostPortPair& host_port_pair, + const SSLInfo& ssl_info); // Returns true iff we have any static public key pins for the |host| and // iff its set of required pins is the set we expect for Google @@ -306,9 +343,13 @@ class NET_EXPORT TransportSecurityState static bool IsBuildTimely(); // Helper method for actually checking pins. - bool CheckPublicKeyPinsImpl(const std::string& host, - const HashValueVector& hashes, - std::string* failure_log); + bool CheckPublicKeyPinsImpl( + const HostPortPair& host_port_pair, + const HashValueVector& hashes, + const X509Certificate* served_certificate_chain, + const X509Certificate* validated_certificate_chain, + const PublicKeyPinReportStatus report_status, + std::string* failure_log); // If a Delegate is present, notify it that the internal state has // changed. @@ -325,7 +366,8 @@ class NET_EXPORT TransportSecurityState const base::Time& last_observed, const base::Time& expiry, bool include_subdomains, - const HashValueVector& hashes); + const HashValueVector& hashes, + const GURL& report_uri); // Enable TransportSecurity for |host|. |state| supercedes any previous // state for the |host|, including static entries. @@ -344,6 +386,8 @@ class NET_EXPORT TransportSecurityState Delegate* delegate_; + ReportSender* report_sender_; + // True if static pins should be used. bool enable_static_pins_; diff --git a/chromium/net/http/transport_security_state_static.h b/chromium/net/http/transport_security_state_static.h index ea645a6653c..6fbfee87a75 100644 --- a/chromium/net/http/transport_security_state_static.h +++ b/chromium/net/http/transport_security_state_static.h @@ -269,6 +269,12 @@ enum SecondLevelDomainName { DOMAIN_GVT3_COM, DOMAIN_GVT2_COM, DOMAIN_GOOGLE, + DOMAIN_GGPHT_COM, + DOMAIN_BLOGSPOT_COM, + DOMAIN_DROPBOXSTATIC_COM, + DOMAIN_DROPBOXUSERCONTENT_COM, + DOMAIN_WITHYOUTUBE_COM, + DOMAIN_WITHGOOGLE_COM, // Boundary value for UMA_HISTOGRAM_ENUMERATION. DOMAIN_NUM_EVENTS, }; @@ -536,6 +542,9 @@ static const char* const kNoRejectedPublicKeys[] = { NULL, }; +// kNoReportURI is a placeholder for when a pinset does not have a report URI. +static const char kNoReportURI[] = ""; + static const char* const kTestAcceptableCerts[] = { kSPKIHash_TestSPKI, NULL, @@ -546,6 +555,7 @@ static const char* const kGoogleAcceptableCerts[] = { kSPKIHash_GeoTrustGlobal, NULL, }; +static const char kGoogleReportURI[] = "http://clients3.google.com/cert_upload_json"; static const char* const kTorAcceptableCerts[] = { kSPKIHash_RapidSSL, kSPKIHash_DigiCertEVRoot, @@ -646,6 +656,7 @@ static const char* const kDropboxAcceptableCerts[] = { kSPKIHash_ThawtePrimaryRootCA, NULL, }; +static const char kDropboxReportURI[] = "https://log.getdropbox.com/hpkp"; static const char* const kFacebookAcceptableCerts[] = { kSPKIHash_SymantecClass3EVG3, kSPKIHash_DigiCertECCSecureServerCA, @@ -664,17 +675,18 @@ static const char* const kSpideroakAcceptableCerts[] = { struct Pinset { const char *const *const accepted_pins; const char *const *const rejected_pins; + const char *const report_uri; }; static const struct Pinset kPinsets[] = { - {kTestAcceptableCerts, kNoRejectedPublicKeys}, - {kGoogleAcceptableCerts, kNoRejectedPublicKeys}, - {kTorAcceptableCerts, kNoRejectedPublicKeys}, - {kTwitterComAcceptableCerts, kNoRejectedPublicKeys}, - {kTwitterCDNAcceptableCerts, kNoRejectedPublicKeys}, - {kDropboxAcceptableCerts, kNoRejectedPublicKeys}, - {kFacebookAcceptableCerts, kNoRejectedPublicKeys}, - {kSpideroakAcceptableCerts, kNoRejectedPublicKeys}, + {kTestAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI}, + {kGoogleAcceptableCerts, kNoRejectedPublicKeys, kGoogleReportURI}, + {kTorAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI}, + {kTwitterComAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI}, + {kTwitterCDNAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI}, + {kDropboxAcceptableCerts, kNoRejectedPublicKeys, kDropboxReportURI}, + {kFacebookAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI}, + {kSpideroakAcceptableCerts, kNoRejectedPublicKeys, kNoReportURI}, }; // kHSTSHuffmanTree describes a Huffman tree. The nodes of the tree are pairs @@ -683,2250 +695,2789 @@ static const struct Pinset kPinsets[] = { // value has the MSB set then it represents a literal leaf value. Otherwise // it's a pointer to the n'th element of the array. static const uint8 kHSTSHuffmanTree[] = { - 0xe4, 0xf5, 0x00, 0xf2, 0x01, 0x80, 0xb9, 0xb8, 0x03, 0xb1, 0xb7, 0xb6, - 0xb5, 0x05, 0xb0, 0x06, 0x04, 0x07, 0x08, 0xea, 0xfa, 0x09, 0xe6, 0x0a, - 0x0b, 0xed, 0xe9, 0x0c, 0xf7, 0xeb, 0x0e, 0xe3, 0x0f, 0xe1, 0x0d, 0x10, - 0x02, 0x11, 0xb3, 0xb2, 0xf1, 0xb4, 0x13, 0x14, 0xf8, 0x15, 0xf6, 0x16, - 0xae, 0x17, 0xe7, 0x18, 0xef, 0x19, 0x1a, 0xff, 0xe2, 0xe8, 0xf3, 0x1c, - 0xe5, 0x1d, 0xee, 0xec, 0xad, 0xf9, 0x20, 0xf0, 0x21, 0xf4, 0x1f, 0x22, - 0x1e, 0x23, 0x1b, 0x24, 0x12, 0x25, + 0xf5, 0xe4, 0x00, 0xf2, 0x01, 0x80, 0xb2, 0xf1, 0xb9, 0xb6, 0xb8, 0x04, + 0xb4, 0x05, 0x03, 0x06, 0xb1, 0xb0, 0xb5, 0xb7, 0x09, 0xb3, 0x08, 0x0a, + 0x0b, 0xea, 0x07, 0x0c, 0xe6, 0x0d, 0x0e, 0xed, 0xe9, 0x0f, 0xae, 0xf7, + 0x11, 0xe7, 0x12, 0xef, 0x10, 0x13, 0x02, 0x14, 0xeb, 0xe2, 0xe3, 0x16, + 0xe1, 0x17, 0x18, 0xff, 0xfa, 0xf8, 0xf6, 0x1a, 0x1b, 0xe8, 0xf3, 0x1c, + 0xe5, 0x1d, 0xec, 0xee, 0xad, 0xf9, 0x20, 0xf0, 0xf4, 0x21, 0x1f, 0x22, + 0x1e, 0x23, 0x19, 0x24, 0x15, 0x25, }; static const uint8 kPreloadedHSTSData[] = { - 0xfe, 0x9b, 0x3b, 0x28, 0x89, 0x1a, 0x22, 0x5b, 0xcd, 0x15, 0x73, 0xae, - 0xdf, 0xe7, 0x5f, 0xff, 0x3f, 0x1d, 0xa3, 0x0a, 0x6e, 0xd7, 0xcf, 0x9d, - 0x74, 0x68, 0xea, 0x69, 0xfd, 0x00, 0x5d, 0x13, 0xaf, 0xff, 0x68, 0x2b, - 0xe0, 0xe6, 0xff, 0x18, 0xe1, 0xd7, 0x66, 0x8e, 0xbd, 0x11, 0x23, 0x44, - 0x5b, 0x4d, 0x44, 0x2e, 0x24, 0xc8, 0x56, 0xee, 0xe8, 0xea, 0xe9, 0xe2, - 0xe8, 0xbe, 0xff, 0x98, 0x14, 0xd2, 0x0e, 0xed, 0x3a, 0xf0, 0x13, 0x63, - 0xa9, 0x0f, 0x52, 0x0e, 0x2f, 0xff, 0x3c, 0xba, 0xea, 0x38, 0xfd, 0x58, - 0xab, 0x15, 0x64, 0xeb, 0xff, 0xc8, 0x22, 0xfb, 0xf9, 0xce, 0xeb, 0x18, - 0x3a, 0xec, 0xdc, 0xab, 0x39, 0x56, 0xf7, 0xa6, 0x97, 0xd1, 0x6b, 0xfd, - 0xfc, 0xef, 0xab, 0x4d, 0x15, 0x31, 0xa9, 0xbf, 0x9b, 0xc4, 0x9d, 0x8c, - 0x9d, 0x4e, 0x7e, 0x70, 0x89, 0x7f, 0x71, 0x24, 0xeb, 0x43, 0xaf, 0xf3, - 0xfb, 0xb4, 0x35, 0xd5, 0xce, 0xb0, 0xb9, 0xf0, 0x89, 0x5d, 0xa6, 0x56, - 0x0b, 0x86, 0x2f, 0x09, 0x8c, 0x87, 0xc7, 0x1d, 0x84, 0x83, 0x4b, 0x53, - 0xd1, 0x85, 0xf9, 0x84, 0x0d, 0xff, 0xff, 0xd0, 0xb9, 0x93, 0xbd, 0x0f, - 0x7a, 0xe3, 0x8a, 0x27, 0x39, 0x9e, 0x4e, 0xbf, 0x76, 0x51, 0x12, 0x34, - 0x54, 0x57, 0xff, 0xe8, 0x68, 0xbe, 0xb3, 0x79, 0x0c, 0x66, 0xf2, 0x3a, - 0xd3, 0x62, 0x21, 0xa7, 0x19, 0xdf, 0xf8, 0x18, 0xb9, 0xa7, 0xb0, 0x53, - 0xe7, 0x5f, 0xec, 0xcd, 0x80, 0xf8, 0x03, 0xaf, 0xf3, 0xba, 0x08, 0x85, - 0x5c, 0xeb, 0xa0, 0x27, 0x5f, 0x71, 0x39, 0x32, 0x87, 0xf1, 0xc3, 0x16, - 0x0c, 0xaf, 0xdd, 0x94, 0x44, 0x8d, 0x15, 0xed, 0xf9, 0x15, 0x48, 0x3b, - 0x1d, 0x73, 0xfa, 0x75, 0xa6, 0xc3, 0xf3, 0xe9, 0x9f, 0xa5, 0x57, 0xff, - 0x4d, 0x0d, 0x9b, 0x3b, 0x28, 0x89, 0x1a, 0x24, 0x6b, 0xff, 0xd3, 0x2e, - 0x1b, 0x36, 0x76, 0x51, 0x12, 0x34, 0x4f, 0x17, 0xff, 0xa6, 0x5c, 0x36, - 0x6c, 0xec, 0xa2, 0x24, 0x68, 0x9f, 0xef, 0xff, 0x4c, 0xb8, 0x6c, 0xd9, - 0xd9, 0x44, 0x48, 0xd1, 0x43, 0x5f, 0xfc, 0xb8, 0x6c, 0xd9, 0xd9, 0x44, - 0x48, 0xd1, 0x44, 0x5f, 0xf9, 0xb3, 0x07, 0x5e, 0x1f, 0x4e, 0xd3, 0xaa, - 0x64, 0x48, 0xba, 0x85, 0xff, 0x99, 0x4e, 0x6f, 0x9f, 0x06, 0x2c, 0xeb, - 0xf7, 0x65, 0x11, 0x23, 0x45, 0x23, 0x7f, 0xce, 0xd7, 0xee, 0xcf, 0xdd, - 0x8e, 0xbd, 0x0d, 0x9b, 0x0f, 0xb0, 0x4c, 0xef, 0xff, 0xec, 0x07, 0x1f, - 0xcc, 0xdf, 0x18, 0xf7, 0x5a, 0x7f, 0x4a, 0xb4, 0xce, 0x99, 0xda, 0xe1, - 0x57, 0x3c, 0x65, 0x7e, 0xec, 0xa2, 0x24, 0x68, 0x94, 0x2f, 0xff, 0x0c, - 0x7f, 0x5e, 0x44, 0x2d, 0x1c, 0x59, 0xd7, 0xd3, 0x43, 0x66, 0xc3, 0xfc, - 0x59, 0x9d, 0x6c, 0xcc, 0x10, 0x6c, 0xe3, 0x80, 0x21, 0x31, 0x28, 0x7c, - 0xa1, 0x5a, 0xbc, 0x2e, 0x3b, 0x0b, 0xc5, 0x9b, 0x71, 0x47, 0xd5, 0x79, - 0xf9, 0x5f, 0x50, 0xe8, 0x0c, 0x6b, 0xca, 0xa1, 0x77, 0x7f, 0xfa, 0x65, - 0xc3, 0x66, 0xce, 0xca, 0x22, 0x46, 0x89, 0xce, 0xff, 0xf4, 0xcb, 0x86, - 0xcd, 0x9d, 0x94, 0x44, 0x8d, 0x14, 0x4d, 0xfc, 0x9a, 0x65, 0xa9, 0xe9, - 0xd7, 0xf9, 0xf6, 0xf3, 0x3d, 0x03, 0xe9, 0xd7, 0xba, 0xd9, 0xb8, 0x7c, - 0xde, 0x4b, 0xab, 0xa9, 0xa5, 0xe9, 0x5c, 0x30, 0xbd, 0xbf, 0x76, 0x51, - 0x12, 0x34, 0x43, 0x97, 0xf0, 0x65, 0xd4, 0x71, 0x3a, 0xd3, 0x61, 0xef, - 0x70, 0xce, 0xff, 0x9f, 0xb9, 0x2e, 0x3e, 0xed, 0x3a, 0xfa, 0x51, 0x12, - 0x34, 0x45, 0xf7, 0xec, 0x65, 0xb1, 0xa3, 0xab, 0xa7, 0xa9, 0xe4, 0xb6, - 0xff, 0x6b, 0x01, 0xcc, 0xf6, 0x0e, 0xb8, 0x76, 0x3a, 0xff, 0xbe, 0x2e, - 0xbf, 0x20, 0xe3, 0x9d, 0x4e, 0x79, 0xe8, 0x2d, 0x76, 0xb7, 0x3a, 0xfb, - 0xed, 0x75, 0x0a, 0xa5, 0x9b, 0x98, 0x17, 0xbf, 0x46, 0xdf, 0xce, 0x1d, - 0x69, 0xb6, 0x4f, 0x47, 0x21, 0x18, 0xc9, 0x27, 0x21, 0x02, 0x2b, 0x33, - 0xc4, 0x17, 0xff, 0xa6, 0x5c, 0x36, 0x6c, 0xec, 0xa2, 0x24, 0x68, 0x99, - 0x2f, 0xf4, 0xd9, 0xd9, 0x44, 0x48, 0xd1, 0x6f, 0x5f, 0xfe, 0x99, 0x70, - 0xd9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x93, 0xb9, 0x5a, 0x9f, 0x0e, 0xbf, - 0xb7, 0xf7, 0xcf, 0x63, 0xd3, 0xae, 0xe4, 0xd3, 0xe9, 0xe9, 0x41, 0x05, - 0x3a, 0xbd, 0x76, 0xc7, 0xf3, 0x8d, 0x9a, 0x57, 0x9c, 0x7f, 0xe6, 0x15, - 0x37, 0xfa, 0x6c, 0xec, 0xa2, 0x24, 0x68, 0x87, 0x6f, 0xdd, 0x94, 0x44, - 0x8d, 0x12, 0xc5, 0xf6, 0x7a, 0xb4, 0x3a, 0xfd, 0x32, 0xe1, 0xb3, 0x61, - 0xea, 0x4f, 0x19, 0xdf, 0xe9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x30, 0xbe, - 0x99, 0xb9, 0xa3, 0xaf, 0xd9, 0xff, 0x5e, 0x47, 0x5f, 0xfe, 0x7f, 0xa7, - 0xae, 0xd0, 0x71, 0xc6, 0x47, 0x5f, 0xbb, 0x28, 0x89, 0x1a, 0x23, 0xdb, - 0xed, 0x46, 0xf3, 0x8e, 0xb9, 0xb3, 0x61, 0xeb, 0xfc, 0xce, 0xd3, 0x32, - 0x8f, 0x4e, 0x93, 0xc4, 0x27, 0xef, 0xdd, 0x94, 0x44, 0x8d, 0x16, 0x1d, - 0xfe, 0x68, 0xbe, 0x6b, 0x04, 0xeb, 0x4d, 0x87, 0xc5, 0xb9, 0x9d, 0xfe, - 0x9b, 0x3b, 0x28, 0x89, 0x1a, 0x2e, 0x7a, 0x75, 0x66, 0x3b, 0x42, 0x4d, - 0xa8, 0x72, 0x3f, 0x48, 0xc5, 0x97, 0x09, 0xef, 0x94, 0xdf, 0xe9, 0xb3, - 0xb2, 0x88, 0x91, 0xa2, 0x1e, 0xbe, 0x94, 0x44, 0x8d, 0x11, 0x35, 0xfe, - 0xf8, 0x63, 0x7e, 0x3c, 0xe3, 0xab, 0xa7, 0xc5, 0xf2, 0xdb, 0xff, 0xf3, - 0xf7, 0xde, 0x3c, 0xe6, 0x5d, 0xd7, 0xac, 0x01, 0xd7, 0xfd, 0xce, 0x3c, - 0xe6, 0xe7, 0x5c, 0xeb, 0x7f, 0x88, 0x90, 0x85, 0x7b, 0xfe, 0x4f, 0xa7, - 0xf3, 0xd7, 0xe9, 0xd5, 0x87, 0xbf, 0x05, 0x17, 0xff, 0xf7, 0xf8, 0xfd, - 0xf7, 0x58, 0x0f, 0x86, 0x25, 0x9d, 0x3a, 0xef, 0xac, 0xeb, 0xff, 0xd9, - 0xcf, 0x3b, 0x69, 0xd3, 0x7f, 0xba, 0xce, 0xac, 0x45, 0xee, 0xeb, 0x7c, - 0x16, 0xbe, 0xf8, 0x63, 0xc9, 0xa2, 0x17, 0xbf, 0x81, 0xcc, 0xd8, 0x22, - 0x75, 0xa6, 0xc5, 0x4f, 0x7c, 0x8c, 0x47, 0x50, 0xdd, 0x09, 0x84, 0xe3, - 0x0b, 0xfc, 0xfe, 0xea, 0x6f, 0xe8, 0x27, 0x5f, 0x95, 0x9d, 0x26, 0xd3, - 0xe9, 0xd7, 0x07, 0x87, 0x5f, 0x03, 0x05, 0x93, 0xae, 0x4f, 0x9d, 0x6f, - 0xa1, 0xb6, 0xe1, 0x0d, 0xfe, 0xdf, 0xfb, 0xb4, 0x22, 0xa1, 0xd7, 0xfe, - 0x76, 0x47, 0x27, 0x42, 0xd6, 0x87, 0x54, 0x1f, 0xa0, 0x4d, 0xaf, 0xff, - 0xfe, 0xe0, 0x40, 0x99, 0xd6, 0x47, 0x27, 0x73, 0x00, 0xfa, 0xd3, 0xa8, - 0x75, 0xff, 0xe4, 0x65, 0xb9, 0xbb, 0x7c, 0x2e, 0x20, 0x4e, 0xba, 0x15, - 0x1d, 0x69, 0xf7, 0x13, 0x90, 0x52, 0x13, 0x52, 0x21, 0xe3, 0x9c, 0x25, - 0xdd, 0x3c, 0xa1, 0xd7, 0xee, 0x47, 0xe1, 0xa7, 0x5f, 0xc9, 0xd1, 0xcc, - 0xe9, 0xd7, 0xf9, 0xba, 0x7d, 0x2b, 0x72, 0xb4, 0xad, 0x1d, 0x7c, 0x9a, - 0x4f, 0x4e, 0xbc, 0xc3, 0x0c, 0x15, 0x7e, 0x81, 0xff, 0x30, 0xa9, 0x8b, - 0xfb, 0xf4, 0x7d, 0x9c, 0xf9, 0xd4, 0x04, 0x4e, 0x7a, 0x80, 0x26, 0xb7, - 0xdc, 0x88, 0x83, 0xaf, 0xfe, 0xf5, 0x19, 0xf1, 0xc7, 0x4e, 0x85, 0x5c, - 0xeb, 0xf8, 0x43, 0xf4, 0xd9, 0xce, 0xbf, 0xf2, 0x28, 0xe2, 0xfa, 0x74, - 0x59, 0xd7, 0xf6, 0x4e, 0x0b, 0x73, 0x47, 0x5f, 0x60, 0x33, 0x63, 0xaf, - 0x95, 0xfc, 0x3a, 0xb2, 0x75, 0xdd, 0x73, 0xab, 0x15, 0x5f, 0xc8, 0x9b, - 0x72, 0xa4, 0x87, 0x02, 0xb9, 0x83, 0x23, 0xeb, 0x4a, 0xe1, 0x60, 0x9d, - 0xfc, 0xba, 0x71, 0x0a, 0xa2, 0xbb, 0xfb, 0x18, 0x7c, 0x02, 0x1d, 0x79, - 0xc3, 0xe9, 0xd7, 0xff, 0xff, 0x84, 0x77, 0x75, 0x07, 0x01, 0xc4, 0x67, - 0xc6, 0xb3, 0x76, 0xf7, 0x18, 0x3a, 0xfc, 0x9f, 0x0b, 0xec, 0x75, 0xff, - 0xfe, 0xcd, 0xdb, 0xa5, 0xe0, 0xf8, 0x54, 0x9c, 0xd9, 0x33, 0xa7, 0x5f, - 0xff, 0xf9, 0x8f, 0x03, 0x92, 0xe2, 0x0e, 0x07, 0x7f, 0xf8, 0x86, 0x31, - 0x43, 0xaf, 0xf6, 0xed, 0xd2, 0x81, 0x7d, 0xce, 0xbf, 0xd0, 0xc0, 0x59, - 0x7f, 0xc1, 0xd4, 0xe8, 0xda, 0x47, 0x11, 0x36, 0xbe, 0xf7, 0xe9, 0xb1, - 0xd7, 0xfb, 0xfc, 0x41, 0xf7, 0xca, 0xce, 0xbf, 0xdb, 0x3a, 0xc5, 0xf7, - 0xf4, 0xeb, 0x3b, 0x4f, 0xa6, 0x0d, 0x69, 0xd5, 0x5f, 0xe3, 0xda, 0x13, - 0xf6, 0x33, 0xe8, 0x2d, 0x18, 0x46, 0x5f, 0xff, 0x75, 0x03, 0x3f, 0x3f, - 0x8d, 0x07, 0xd5, 0xe7, 0xce, 0xb8, 0x2d, 0x3a, 0xfc, 0xfe, 0xeb, 0x6f, - 0x9d, 0x7a, 0x3f, 0xa3, 0xae, 0x0e, 0xc7, 0x5e, 0x1f, 0xb2, 0xd3, 0x65, - 0xd1, 0xbb, 0xf8, 0x32, 0xf0, 0x0d, 0xd8, 0x3a, 0x9c, 0xf9, 0x50, 0xce, - 0xff, 0xfc, 0x17, 0xff, 0x81, 0x0a, 0xaf, 0x19, 0xf9, 0xec, 0xf9, 0xd7, - 0xff, 0x71, 0xd4, 0xf1, 0xf1, 0x8f, 0xbf, 0xce, 0xbf, 0xde, 0x37, 0x6a, - 0x70, 0x2b, 0x3a, 0xbd, 0x3f, 0xb1, 0x45, 0xbf, 0xf7, 0x59, 0xf1, 0xa7, - 0x4d, 0xa3, 0xe7, 0x53, 0x9f, 0x18, 0x48, 0xae, 0x8f, 0x4e, 0xbf, 0xfe, - 0xf0, 0x2f, 0xa7, 0xd8, 0x70, 0x1c, 0x46, 0x4e, 0xbf, 0xff, 0xfb, 0x5d, - 0x17, 0x67, 0xc7, 0x9f, 0xa3, 0x73, 0x7f, 0xe4, 0xe1, 0xcd, 0x1d, 0x5d, - 0x46, 0x38, 0xa8, 0x57, 0xd1, 0xfe, 0x18, 0x6e, 0xd1, 0xd7, 0x32, 0xd3, - 0xa9, 0xcd, 0x0f, 0x42, 0xaf, 0xfe, 0x1f, 0xea, 0x72, 0x7d, 0xf0, 0x59, - 0x3a, 0xfd, 0xd4, 0xd3, 0xee, 0x75, 0x61, 0xf5, 0xc2, 0x25, 0xff, 0xa1, - 0x8e, 0xb8, 0xff, 0x98, 0xa8, 0xea, 0x69, 0xef, 0xf4, 0x82, 0xff, 0xb8, - 0x9d, 0x67, 0x91, 0x9d, 0x3a, 0xff, 0xff, 0xfe, 0xf7, 0x43, 0x91, 0xbf, - 0x80, 0x70, 0x3e, 0x07, 0x37, 0x6e, 0x07, 0x61, 0xc8, 0xdc, 0xea, 0x92, - 0x31, 0x90, 0xe2, 0xf4, 0x44, 0x8d, 0x14, 0xc5, 0x61, 0xe4, 0xc8, 0x8a, - 0xff, 0xd8, 0x3b, 0xb7, 0x5f, 0x7e, 0xb2, 0x75, 0xec, 0x4f, 0x4e, 0xb6, - 0x1d, 0x7b, 0x71, 0xcf, 0x4d, 0x54, 0xe1, 0xba, 0x44, 0x4f, 0x43, 0x4d, - 0xfe, 0xef, 0x23, 0xc2, 0xc0, 0xc9, 0xd7, 0xfb, 0xc6, 0xed, 0x17, 0xcd, - 0x1d, 0x48, 0x7d, 0x50, 0x6d, 0x7f, 0xfe, 0xf5, 0x35, 0xe3, 0x91, 0xaf, - 0xbb, 0x3a, 0xe6, 0x1d, 0x7f, 0x27, 0x21, 0x36, 0x73, 0xaf, 0x35, 0xf7, - 0x3a, 0xff, 0x2c, 0x1c, 0x7d, 0xb1, 0x83, 0xab, 0x0f, 0xef, 0x72, 0xb8, - 0x1c, 0xbf, 0xff, 0xc3, 0x92, 0xff, 0xdf, 0xfa, 0x64, 0x71, 0x8f, 0x0e, - 0xac, 0x9d, 0x7f, 0xe9, 0x3a, 0xf9, 0x9a, 0xc4, 0x13, 0xa9, 0xd1, 0x45, - 0xc6, 0x7b, 0xf7, 0x5e, 0x73, 0xf4, 0xeb, 0xfa, 0x07, 0xc0, 0x1c, 0x4e, - 0xac, 0x3f, 0x64, 0x22, 0x09, 0x45, 0x3b, 0x26, 0xf3, 0x65, 0x76, 0x8b, - 0x02, 0x18, 0x0a, 0x10, 0x4a, 0x33, 0xbd, 0xe3, 0x20, 0x44, 0x96, 0x61, - 0xd5, 0xd8, 0xcc, 0x57, 0x0b, 0xfe, 0x42, 0x2f, 0xd2, 0x01, 0x86, 0x9f, - 0xe3, 0x46, 0xbf, 0xee, 0xc3, 0x1e, 0x20, 0x11, 0xb1, 0xd7, 0xff, 0xfc, - 0xe0, 0xcd, 0xa0, 0x7f, 0xa7, 0x97, 0x85, 0xad, 0x06, 0x47, 0x5f, 0xf3, - 0xb3, 0xc4, 0x75, 0xc0, 0x0e, 0xa5, 0x11, 0xb0, 0x27, 0x61, 0x66, 0xbe, - 0xc1, 0x51, 0x5c, 0xeb, 0xff, 0xff, 0xf7, 0x13, 0xfc, 0xce, 0xbc, 0xef, - 0x0b, 0x0a, 0xaf, 0x19, 0xbb, 0x70, 0x23, 0xee, 0x8e, 0xb7, 0xd1, 0x16, - 0x1a, 0x24, 0xbf, 0xf3, 0xcb, 0xc0, 0xc6, 0x96, 0xe2, 0x75, 0xff, 0xfb, - 0x33, 0x89, 0x2e, 0x67, 0x8d, 0x07, 0x8e, 0xae, 0x75, 0xff, 0xf7, 0xf9, - 0x9e, 0xf8, 0x5b, 0xe7, 0xc1, 0x82, 0x75, 0xff, 0x6f, 0xe1, 0x6f, 0x83, - 0xf9, 0xe3, 0xad, 0xac, 0x44, 0x6c, 0x28, 0x52, 0xd3, 0x49, 0x13, 0xdf, - 0xc3, 0x96, 0xff, 0xff, 0xfc, 0x39, 0xbb, 0x53, 0x43, 0x93, 0xb9, 0x8c, - 0xf1, 0xc5, 0x9f, 0x11, 0x24, 0x9c, 0x75, 0x22, 0x2f, 0x02, 0x6b, 0x7d, - 0xdd, 0x9a, 0xd3, 0xaf, 0xcd, 0x7d, 0xdb, 0xa3, 0xaf, 0xff, 0xff, 0xfd, - 0x82, 0xa7, 0x84, 0xe0, 0x66, 0x65, 0x3e, 0xeb, 0x18, 0x53, 0x89, 0x36, - 0x73, 0x7f, 0x5c, 0x05, 0x5f, 0xff, 0xfd, 0x24, 0x60, 0x01, 0xef, 0x80, - 0xbe, 0xda, 0x97, 0x03, 0xcd, 0xe1, 0x83, 0xae, 0x0e, 0xdb, 0xa6, 0x80, - 0x85, 0x1a, 0x84, 0xfd, 0x3a, 0xbf, 0x5e, 0x4a, 0x2d, 0x82, 0x21, 0x8d, - 0x8e, 0xff, 0x43, 0x71, 0x70, 0x3e, 0x9d, 0x7d, 0x9c, 0x76, 0x4e, 0xbc, - 0xb9, 0x78, 0xe1, 0xe9, 0x41, 0x8d, 0xff, 0xff, 0xf6, 0x76, 0x43, 0x93, - 0xbc, 0x69, 0x30, 0x7d, 0xf0, 0x39, 0x38, 0x73, 0x53, 0x8e, 0xbf, 0xff, - 0x20, 0xff, 0x98, 0xab, 0xec, 0xe2, 0xbc, 0x0f, 0xa7, 0x5f, 0x9d, 0x8f, - 0x1a, 0x64, 0xeb, 0xff, 0x0e, 0xc3, 0x93, 0xb4, 0x17, 0xdc, 0xeb, 0xff, - 0x03, 0x8f, 0xbf, 0x85, 0x6f, 0x9d, 0xea, 0x1d, 0x4e, 0x88, 0xbd, 0x90, - 0x29, 0x13, 0xb5, 0xd4, 0x20, 0xfe, 0xb2, 0x18, 0x5b, 0x5f, 0x67, 0xf2, - 0x7e, 0x3a, 0xf4, 0xf6, 0x70, 0xeb, 0xb0, 0x07, 0x56, 0xca, 0xa2, 0x5b, - 0x1f, 0x56, 0x91, 0xfe, 0x4b, 0x38, 0x7a, 0xfc, 0x9f, 0xd6, 0x7a, 0x75, - 0xfc, 0x07, 0x1e, 0x43, 0x4e, 0xbc, 0xe0, 0x73, 0xaf, 0xd9, 0xfd, 0x43, - 0x3e, 0x0f, 0x15, 0x65, 0x77, 0xf3, 0x1e, 0x27, 0xc5, 0x6e, 0x9f, 0xe7, - 0xc3, 0xa9, 0xa8, 0x88, 0x44, 0x1b, 0xff, 0xf7, 0x43, 0xde, 0xb8, 0xe2, - 0x89, 0xce, 0x67, 0x93, 0xaf, 0x83, 0x1b, 0xfc, 0xea, 0x6a, 0x71, 0xcc, - 0xc3, 0xd3, 0xa4, 0x5c, 0x56, 0xa3, 0xaf, 0xed, 0x4a, 0x50, 0x2a, 0x1d, - 0x4a, 0xc4, 0xdb, 0xfc, 0x2a, 0xff, 0x0f, 0x89, 0xdb, 0xb7, 0x4c, 0x9d, - 0x76, 0xdb, 0x9d, 0x7e, 0xe4, 0x2b, 0xbf, 0xa7, 0x50, 0x0f, 0xee, 0x0e, - 0x55, 0x0c, 0x5f, 0xee, 0xb2, 0x39, 0xc8, 0xf9, 0xd4, 0xe9, 0x82, 0x64, - 0x28, 0x90, 0xc2, 0xfc, 0x9d, 0x06, 0x09, 0xd7, 0xef, 0x73, 0xfe, 0x76, - 0x3a, 0xff, 0x31, 0xfc, 0xe7, 0x8d, 0xf4, 0x75, 0x39, 0xf1, 0x41, 0x5d, - 0x35, 0x1b, 0x5c, 0x33, 0x18, 0x43, 0xdf, 0xf7, 0xf9, 0x8d, 0x81, 0xcd, - 0xce, 0xbf, 0xff, 0xe1, 0x8f, 0x75, 0xb6, 0x20, 0xfc, 0x72, 0x77, 0x8d, - 0x30, 0x27, 0x50, 0xa2, 0x83, 0xe6, 0xf7, 0xfe, 0x4c, 0x67, 0xc6, 0x9f, - 0x90, 0xae, 0x75, 0xff, 0x6f, 0x8f, 0xbb, 0x22, 0xeb, 0x3a, 0xfe, 0xdf, - 0x5c, 0xc8, 0xe9, 0xd7, 0xff, 0xfe, 0x45, 0xf5, 0x33, 0x71, 0x0f, 0xdf, - 0x9e, 0x27, 0x27, 0xd9, 0x73, 0xaa, 0x11, 0x39, 0xf2, 0xda, 0x02, 0x67, - 0x3c, 0x42, 0xfc, 0x35, 0x6f, 0xfb, 0x3b, 0xb3, 0xa7, 0x70, 0x4e, 0xb2, - 0xce, 0xf0, 0x6d, 0xaf, 0x0e, 0x00, 0xea, 0x73, 0x79, 0xb9, 0x15, 0xfd, - 0xbe, 0xb3, 0x05, 0x43, 0xaf, 0x97, 0xe5, 0xfd, 0x3a, 0xb0, 0xf4, 0x50, - 0xb6, 0xff, 0x47, 0xf9, 0x0c, 0xf9, 0x59, 0xd7, 0x83, 0xbf, 0xa7, 0x53, - 0xaa, 0xe8, 0xc8, 0xd6, 0xd2, 0x15, 0x1d, 0x72, 0x82, 0x01, 0x35, 0xbf, - 0xdf, 0x4d, 0xb3, 0x81, 0xf9, 0xd6, 0x64, 0xeb, 0xfb, 0x03, 0x9c, 0x96, - 0xc7, 0x5d, 0x9b, 0xb9, 0xbe, 0xd0, 0x8d, 0xfd, 0xc8, 0x6a, 0xfa, 0x87, - 0x5f, 0xfe, 0x75, 0x14, 0x8f, 0xeb, 0xe2, 0xfb, 0xb4, 0xeb, 0x93, 0x47, - 0x5e, 0xee, 0x6e, 0x75, 0x00, 0xd8, 0xfa, 0x2b, 0x7e, 0x4d, 0x69, 0xd6, - 0x75, 0x21, 0xe4, 0x4e, 0x22, 0xa5, 0x13, 0xb0, 0x47, 0x1f, 0x4b, 0x04, - 0xb0, 0x30, 0xc4, 0xbf, 0x01, 0x06, 0x00, 0x75, 0xff, 0xf9, 0xbc, 0xc6, - 0x78, 0xe2, 0xa0, 0xe7, 0xf8, 0x13, 0xa9, 0x0f, 0xeb, 0xa4, 0xb7, 0xff, - 0xf9, 0x33, 0x76, 0xeb, 0xfc, 0x75, 0xba, 0x03, 0xc3, 0xab, 0x27, 0x5f, - 0xe8, 0x1f, 0x12, 0xd7, 0xa0, 0x3a, 0xff, 0xc1, 0xd7, 0x85, 0xf9, 0xe4, - 0x71, 0xce, 0xbf, 0x67, 0xc3, 0x9b, 0x9d, 0x79, 0x4c, 0xdc, 0xeb, 0x9d, - 0x9f, 0x07, 0x89, 0xf2, 0x7a, 0x14, 0x5b, 0x06, 0x10, 0xd7, 0xff, 0xff, - 0xe0, 0x8f, 0x86, 0x23, 0x76, 0xf6, 0x3d, 0xf1, 0xa0, 0xbe, 0xfc, 0xc4, - 0x1c, 0x50, 0xeb, 0xff, 0xf0, 0x7b, 0xdc, 0xfe, 0xb8, 0x99, 0xe3, 0x9e, - 0xb9, 0xd5, 0x88, 0xe0, 0xe4, 0x22, 0x6f, 0xd8, 0x32, 0xf2, 0xb3, 0xaf, - 0xfe, 0xe6, 0x38, 0xb2, 0x39, 0xfd, 0x41, 0xd6, 0x6f, 0xcf, 0xa5, 0x51, - 0x45, 0xff, 0xf8, 0x18, 0xbf, 0x0a, 0xbe, 0xfa, 0x65, 0xb1, 0xdd, 0x8e, - 0xbf, 0xff, 0xbe, 0x9b, 0x60, 0x3c, 0x2e, 0x1b, 0xd4, 0xda, 0x16, 0x75, - 0xfe, 0xda, 0x16, 0x2f, 0xd6, 0x4e, 0xbf, 0xed, 0xf1, 0x4f, 0x57, 0x9e, - 0x3b, 0x88, 0x90, 0x45, 0xdb, 0xfe, 0xc1, 0xdb, 0xc7, 0xb1, 0x0c, 0x9d, - 0x7f, 0xdd, 0xd9, 0xf6, 0xd8, 0x3d, 0xd8, 0xeb, 0xff, 0x78, 0x67, 0x81, - 0x51, 0x30, 0x54, 0x3a, 0xff, 0x0f, 0x8d, 0x06, 0x78, 0x3d, 0x3a, 0xb0, - 0xfe, 0x82, 0x85, 0x4e, 0x8d, 0x8d, 0x42, 0xde, 0xff, 0xf6, 0xde, 0x35, - 0xc0, 0xf8, 0xfe, 0xb4, 0xfd, 0x3a, 0xff, 0xff, 0xd9, 0xbe, 0x93, 0x18, - 0xf1, 0xcc, 0xfe, 0xb3, 0x6f, 0x18, 0x80, 0x3a, 0xb1, 0x18, 0x08, 0xa1, - 0x5b, 0x2f, 0x36, 0x01, 0x99, 0x48, 0x75, 0xca, 0x30, 0x7d, 0xe1, 0x20, - 0x85, 0x5d, 0x87, 0x5a, 0xd5, 0x35, 0x18, 0x9f, 0xe1, 0xcf, 0x7f, 0xbe, - 0x39, 0xfe, 0x66, 0xc7, 0x5f, 0xfa, 0x3b, 0xcc, 0xfb, 0x8a, 0x7a, 0x75, - 0xff, 0xf0, 0xe6, 0xde, 0x3d, 0x0f, 0xf3, 0x17, 0xeb, 0x07, 0x5f, 0x37, - 0xe9, 0xb1, 0xd7, 0xfd, 0x8c, 0x6e, 0xdd, 0x78, 0xfa, 0x1d, 0x7f, 0xfc, - 0xcf, 0x10, 0x41, 0xe3, 0xcc, 0x87, 0x39, 0x87, 0x5f, 0xf7, 0x11, 0x6f, - 0x83, 0xfd, 0x1d, 0x7f, 0xff, 0x83, 0xfe, 0x85, 0x9f, 0x1f, 0x67, 0x81, - 0xf7, 0xe9, 0x8a, 0x8e, 0xbe, 0x79, 0x3a, 0xfc, 0x23, 0xc6, 0x4a, 0x42, - 0x6d, 0x4e, 0xa9, 0x62, 0x46, 0x5d, 0x3c, 0x85, 0x41, 0x22, 0x55, 0x19, - 0x6d, 0xf2, 0x7d, 0x1c, 0xeb, 0xff, 0xff, 0xc2, 0x8a, 0x72, 0x19, 0xf0, - 0x21, 0x55, 0xe3, 0x37, 0x6e, 0x04, 0x7d, 0xd1, 0xd7, 0xee, 0x23, 0x8e, - 0xc7, 0x5d, 0xf7, 0x5a, 0x29, 0x67, 0x3f, 0xd3, 0x51, 0xe8, 0x90, 0xc4, - 0xa7, 0x65, 0x87, 0x64, 0xf4, 0x6a, 0x4b, 0x08, 0x88, 0xd4, 0xaf, 0xce, - 0x3f, 0x49, 0xc7, 0x5f, 0x7f, 0x51, 0xe9, 0xd7, 0xff, 0x71, 0x3c, 0x27, - 0x43, 0xb4, 0x76, 0x47, 0x5f, 0x27, 0x23, 0x63, 0xaf, 0xa7, 0x3f, 0xdc, - 0xeb, 0xf6, 0xb3, 0xe9, 0xa3, 0xaf, 0xc1, 0x9f, 0x86, 0x3e, 0x75, 0xfd, - 0xc8, 0xdb, 0xc3, 0x7e, 0x75, 0xfb, 0xc8, 0xb5, 0xab, 0x3a, 0xfd, 0x1d, - 0x1d, 0xd0, 0xea, 0x74, 0x55, 0x21, 0x5f, 0xa6, 0x1f, 0x29, 0xa0, 0x27, - 0xbd, 0x84, 0xea, 0x11, 0x49, 0x19, 0x08, 0x59, 0x22, 0xfc, 0x34, 0x2f, - 0xf7, 0x1d, 0x06, 0x3a, 0xa1, 0xd7, 0xf3, 0xa0, 0xc7, 0x54, 0x3a, 0xff, - 0x7b, 0x1e, 0xf7, 0xa9, 0xdf, 0x07, 0xb9, 0xc3, 0x1b, 0x7a, 0x75, 0xfc, - 0xfd, 0xd9, 0xfb, 0xb1, 0xd7, 0x83, 0x1a, 0x3a, 0x9a, 0x79, 0x3e, 0x4b, - 0xaf, 0xff, 0xe4, 0xef, 0x8c, 0x4c, 0x15, 0x38, 0x98, 0xbc, 0x91, 0xd7, - 0xff, 0xfc, 0x9b, 0x75, 0xd7, 0xa0, 0xbf, 0x87, 0xeb, 0x83, 0x8e, 0xb3, - 0xab, 0x11, 0x81, 0xd5, 0x9b, 0xff, 0x77, 0x37, 0xe6, 0xee, 0xbd, 0x9c, - 0xeb, 0xff, 0xff, 0xdd, 0xea, 0x6d, 0xe3, 0x99, 0xf1, 0x76, 0x79, 0x9b, - 0x3e, 0xff, 0x0c, 0x8e, 0xbf, 0xff, 0xf9, 0xd4, 0xe3, 0xf8, 0x1c, 0x0a, - 0x9e, 0x37, 0x6e, 0x90, 0x7c, 0xbe, 0xc7, 0x5f, 0xb7, 0xd2, 0x60, 0x9d, - 0x58, 0x89, 0xf0, 0xbc, 0xd2, 0x26, 0x7b, 0xc8, 0xc6, 0xef, 0xfe, 0x6e, - 0x91, 0x4e, 0x3a, 0x6c, 0xea, 0x1d, 0x7f, 0xc2, 0x16, 0x47, 0x39, 0x1f, - 0x3a, 0xff, 0x71, 0xd8, 0x07, 0x21, 0x67, 0x5f, 0xf2, 0xf3, 0x5e, 0x19, - 0x17, 0x59, 0xd4, 0x03, 0xed, 0x59, 0x9d, 0xff, 0xff, 0x47, 0x79, 0x9f, - 0x4c, 0x1d, 0xb4, 0xf8, 0x20, 0xe3, 0x9d, 0x7d, 0xff, 0x1b, 0x74, 0xea, - 0xdd, 0x10, 0xf0, 0xc5, 0x7f, 0xff, 0xed, 0xf3, 0x60, 0xaa, 0xf1, 0xbb, - 0x7e, 0xec, 0x78, 0xce, 0xfb, 0xeb, 0x9d, 0x7f, 0xf9, 0x88, 0x1d, 0x96, - 0x14, 0x02, 0x0a, 0x1d, 0x7f, 0x33, 0xbb, 0x42, 0xff, 0x3a, 0xff, 0xb9, - 0x0b, 0x1c, 0xe4, 0x7c, 0xeb, 0xec, 0xef, 0xac, 0x1d, 0x4e, 0x88, 0x8d, - 0x17, 0xfc, 0xda, 0xfe, 0xcf, 0xf7, 0xb8, 0xd3, 0xaf, 0xe1, 0xce, 0x0e, - 0x48, 0xeb, 0xe1, 0xcd, 0x78, 0x64, 0xf5, 0xbe, 0x59, 0x7f, 0xd8, 0xbe, - 0x3a, 0x74, 0x2a, 0xe7, 0x50, 0x17, 0x6f, 0xd4, 0x22, 0x94, 0x6f, 0xbb, - 0x94, 0xa2, 0x2f, 0x61, 0x49, 0xc8, 0x54, 0xc1, 0x1e, 0x9e, 0x3f, 0x0d, - 0x09, 0xd0, 0x85, 0xf2, 0x77, 0x7f, 0xec, 0x60, 0x70, 0x38, 0xa3, 0x7d, - 0x3a, 0xff, 0xc3, 0x9e, 0x3b, 0x9c, 0x1c, 0x64, 0xeb, 0xff, 0xfd, 0xc8, - 0xf7, 0x5e, 0x07, 0x27, 0x0e, 0x6b, 0x16, 0xf2, 0x3a, 0x85, 0x14, 0x1a, - 0x3e, 0xa5, 0x62, 0xc8, 0xc4, 0x75, 0xac, 0x9e, 0xa3, 0xde, 0x18, 0xd1, - 0x0d, 0xfb, 0xfb, 0x98, 0x3f, 0xf4, 0x27, 0x5f, 0x85, 0xd7, 0x00, 0x3a, - 0xff, 0x63, 0x3c, 0xcf, 0xb8, 0x0e, 0xbf, 0x87, 0xf0, 0xb4, 0xf9, 0xd6, - 0x69, 0xd4, 0xe6, 0xef, 0xe5, 0x77, 0x86, 0x4e, 0x75, 0xff, 0xff, 0xf7, - 0x33, 0xfa, 0x86, 0x7c, 0x0e, 0x6e, 0xdc, 0x0e, 0xc3, 0x80, 0xe2, 0x32, - 0x75, 0xc1, 0x50, 0xea, 0x44, 0x58, 0xf4, 0x6b, 0xf0, 0x80, 0xbf, 0xb3, - 0x61, 0xcd, 0xf4, 0x75, 0xff, 0xff, 0xf9, 0xba, 0xd0, 0x5f, 0xe8, 0x0c, - 0x16, 0x7c, 0x0e, 0x75, 0xc7, 0xfc, 0xc5, 0x47, 0x5f, 0xfd, 0xbb, 0x75, - 0x8b, 0xdd, 0xf9, 0xc7, 0x3a, 0xb7, 0x46, 0x4f, 0x61, 0x09, 0x6d, 0x1d, - 0x41, 0x37, 0x3e, 0x4a, 0x6f, 0xec, 0xdd, 0xaf, 0xeb, 0x9d, 0x7e, 0x1c, - 0xe4, 0x7c, 0xeb, 0x3e, 0xe7, 0xa4, 0xb2, 0xdb, 0xef, 0x12, 0xd9, 0x83, - 0xaf, 0xdb, 0x78, 0x0b, 0xb2, 0x75, 0xff, 0xff, 0x0b, 0xfb, 0xbb, 0x74, - 0x17, 0xf8, 0xe0, 0x13, 0x3a, 0xc9, 0xd5, 0x08, 0x91, 0xf9, 0x5d, 0x01, - 0x71, 0xa5, 0x0b, 0x59, 0x25, 0xe3, 0x6c, 0x43, 0x44, 0x4d, 0x35, 0x19, - 0x78, 0x5d, 0x67, 0x14, 0x79, 0x85, 0xbd, 0xf9, 0xa9, 0xdc, 0xdc, 0xeb, - 0xda, 0xe6, 0x1d, 0x7e, 0xcd, 0x6d, 0x8c, 0x1d, 0x5b, 0x9f, 0x53, 0x24, - 0xfc, 0x1b, 0xbf, 0xff, 0x26, 0xd9, 0x20, 0x71, 0x31, 0x4f, 0x0a, 0x05, - 0xce, 0xbf, 0xfc, 0xfb, 0xb7, 0x5f, 0x8d, 0x95, 0x0e, 0x6e, 0x75, 0xff, - 0xcd, 0x7e, 0x6c, 0x98, 0x3b, 0xb7, 0x47, 0x5f, 0x2a, 0xfe, 0x70, 0xeb, - 0x91, 0x67, 0x5f, 0xff, 0xfb, 0x76, 0xc6, 0xfe, 0x04, 0x2a, 0xbc, 0x66, - 0xed, 0xc0, 0x8f, 0xba, 0x3a, 0x96, 0x88, 0xa5, 0x42, 0xb7, 0xa7, 0x92, - 0x7e, 0x3a, 0xb6, 0x47, 0xae, 0x42, 0xb6, 0x78, 0x96, 0xff, 0xff, 0xfc, - 0xfb, 0xe8, 0x2f, 0xbf, 0x8e, 0x60, 0x3c, 0x0e, 0x05, 0x4f, 0x1a, 0xf7, - 0xd4, 0xf9, 0xd7, 0xe7, 0x1d, 0xe3, 0x63, 0xaf, 0xff, 0xff, 0xfe, 0x5e, - 0x49, 0xf8, 0xeb, 0xfe, 0x6b, 0x4f, 0xde, 0xb8, 0xe6, 0xd8, 0x1d, 0x05, - 0x91, 0x75, 0x9d, 0x7e, 0x8f, 0x7c, 0xc6, 0xc7, 0x56, 0x23, 0x1d, 0x21, - 0x3b, 0x79, 0x3d, 0x73, 0xaf, 0xe0, 0x0e, 0x72, 0x3e, 0x75, 0xfb, 0xfb, - 0xb5, 0x3a, 0x75, 0x61, 0xe9, 0xe8, 0xae, 0xb6, 0x44, 0x7f, 0xad, 0xd7, - 0xfb, 0x60, 0xbf, 0xd6, 0x9f, 0x3a, 0xff, 0xce, 0xa2, 0xa0, 0xe0, 0xb3, - 0xe5, 0x67, 0x56, 0x1f, 0xb6, 0xe6, 0x77, 0xfe, 0xcc, 0xf7, 0x5e, 0x3b, - 0xa0, 0x68, 0xeb, 0xfd, 0xdc, 0x97, 0x13, 0xac, 0x9d, 0x76, 0x7c, 0x07, - 0xe9, 0x88, 0x37, 0xdb, 0x20, 0xfc, 0xeb, 0xf6, 0x73, 0x90, 0xd3, 0xaf, - 0xef, 0xa7, 0x76, 0xc9, 0x1d, 0x4e, 0xbc, 0x91, 0x86, 0x2a, 0x2c, 0x6e, - 0x9a, 0x91, 0x9c, 0xf4, 0xe1, 0x70, 0x8d, 0xe4, 0x3b, 0xa2, 0x16, 0xa3, - 0x09, 0xbd, 0x42, 0x58, 0x25, 0x93, 0xc4, 0x2a, 0x89, 0xaf, 0x44, 0xb0, - 0xeb, 0xff, 0x33, 0xe3, 0xe3, 0x8c, 0x62, 0x68, 0xea, 0x9f, 0xcf, 0x69, - 0xc6, 0xa8, 0xeb, 0xfb, 0x16, 0xfc, 0x8e, 0x1d, 0x77, 0x86, 0x4e, 0xaf, - 0x07, 0x88, 0x02, 0xbb, 0xff, 0xed, 0xda, 0x2f, 0xe1, 0x62, 0xea, 0x7d, - 0x36, 0x3a, 0x9d, 0x18, 0x98, 0x9c, 0x84, 0x97, 0xee, 0xf8, 0x19, 0xcc, - 0x1d, 0x7d, 0xc8, 0xf5, 0xce, 0xa7, 0x3c, 0xd8, 0x2c, 0xbf, 0xb6, 0x65, - 0xb3, 0xff, 0x76, 0x3a, 0xfc, 0xb4, 0x06, 0x00, 0xeb, 0x32, 0x75, 0xce, - 0xb3, 0xad, 0xf3, 0xab, 0xa6, 0x96, 0x05, 0x68, 0x07, 0xad, 0xc3, 0x6b, - 0xef, 0xea, 0x37, 0x3a, 0xe6, 0x60, 0xeb, 0xfa, 0x18, 0x7f, 0xe6, 0xc7, - 0x5f, 0xee, 0x27, 0x77, 0x68, 0xb9, 0xd4, 0xad, 0x26, 0xd6, 0xe6, 0xd8, - 0xf8, 0x84, 0x4b, 0x22, 0x11, 0x60, 0x96, 0xdf, 0xe6, 0x31, 0xa2, 0x18, - 0xd1, 0xd7, 0xed, 0xd8, 0x81, 0xf4, 0xeb, 0x85, 0x43, 0xad, 0xa4, 0x37, - 0xe1, 0x29, 0xbf, 0xff, 0x9d, 0x63, 0x92, 0xdf, 0xe3, 0x1c, 0x5b, 0xe7, - 0xce, 0xbf, 0xff, 0x3f, 0x5e, 0x58, 0xb7, 0x93, 0x53, 0x41, 0x59, 0xd4, - 0xe9, 0xa1, 0x32, 0xe3, 0xc2, 0x69, 0xe5, 0x8b, 0xfb, 0xb8, 0xea, 0x38, - 0x9d, 0x78, 0x61, 0x67, 0x5d, 0xeb, 0x9d, 0x4d, 0x3d, 0xb4, 0x2b, 0x11, - 0xaa, 0x56, 0x9f, 0x46, 0x2e, 0x7c, 0x32, 0x9f, 0xe3, 0xdc, 0x56, 0xcb, - 0x4f, 0x2b, 0x67, 0x68, 0x59, 0x34, 0xac, 0x12, 0xb6, 0xf2, 0x94, 0x36, - 0xa4, 0x7b, 0x72, 0x9c, 0xd5, 0xde, 0x59, 0x22, 0x47, 0xc6, 0xcc, 0xa5, - 0x9e, 0xcb, 0xbc, 0x5c, 0xa0, 0xfe, 0x52, 0xf6, 0x22, 0x51, 0x87, 0xb0, - 0xc6, 0x1a, 0x48, 0x96, 0xa7, 0x33, 0x7f, 0x3e, 0xa4, 0x18, 0xcf, 0x67, - 0x43, 0xa9, 0x87, 0xa9, 0xe8, 0xe2, 0xfc, 0xc7, 0x50, 0xaa, 0x13, 0x97, - 0xff, 0xf0, 0x65, 0x36, 0xff, 0xeb, 0xe6, 0xf3, 0xf8, 0x22, 0x14, 0x3a, - 0xa6, 0x55, 0x34, 0x92, 0x8d, 0xef, 0xdd, 0x94, 0x44, 0x8d, 0x14, 0xed, - 0xd9, 0xb9, 0xd7, 0xff, 0x82, 0x11, 0x41, 0x7e, 0x22, 0xf3, 0x47, 0x5a, - 0x6c, 0x44, 0x7e, 0xe6, 0x6b, 0x16, 0xbf, 0x76, 0x51, 0x12, 0x34, 0x54, - 0x77, 0xfe, 0x86, 0xcd, 0x9d, 0x94, 0x44, 0x8d, 0x13, 0x45, 0xf0, 0xbe, - 0x6e, 0x75, 0x62, 0x27, 0x56, 0x67, 0xf4, 0xab, 0xfd, 0xe6, 0x27, 0x4d, - 0xf4, 0xd8, 0xea, 0x98, 0xf9, 0xdc, 0xbe, 0xfd, 0xd9, 0x44, 0x48, 0xd1, - 0x57, 0xdf, 0xd9, 0x39, 0xc7, 0x81, 0x3a, 0xd3, 0x61, 0xf0, 0x74, 0xce, - 0xfd, 0xd9, 0x44, 0x48, 0xd1, 0x5b, 0x5f, 0xf3, 0x66, 0xce, 0xca, 0x22, - 0x46, 0x89, 0x06, 0xd3, 0x61, 0xfc, 0x41, 0x9d, 0xff, 0xd3, 0x43, 0x66, - 0xce, 0xca, 0x22, 0x46, 0x89, 0x0e, 0xff, 0xda, 0x9b, 0x3e, 0x80, 0xc1, - 0x64, 0xeb, 0xd1, 0x12, 0x3c, 0x60, 0x74, 0xe7, 0xcb, 0x23, 0xeb, 0xb8, - 0xae, 0x75, 0xff, 0x9b, 0xc7, 0xfe, 0x95, 0x9d, 0x4f, 0x82, 0x75, 0xff, - 0xe5, 0x60, 0xac, 0x15, 0x9e, 0x3a, 0xc6, 0x38, 0x9d, 0x3a, 0xdb, 0x9d, - 0x72, 0x09, 0xd4, 0x03, 0x4a, 0xc8, 0x8d, 0xfb, 0x30, 0x7d, 0xd1, 0xd7, - 0xe8, 0x07, 0x97, 0x13, 0xaf, 0xfd, 0xdf, 0xf9, 0x18, 0x96, 0x0c, 0x8e, - 0xbe, 0x94, 0x44, 0x8d, 0x16, 0x25, 0xe0, 0x8b, 0x4e, 0xbf, 0xd2, 0x7c, - 0xef, 0xbe, 0xfc, 0xea, 0xd9, 0x1c, 0x38, 0x4f, 0xd3, 0xef, 0x96, 0x84, - 0x6e, 0xfd, 0x9d, 0x71, 0x50, 0xeb, 0xf7, 0x99, 0xec, 0xeb, 0x9d, 0x7b, - 0x4e, 0x27, 0x5b, 0x8e, 0x78, 0xa8, 0x57, 0x7f, 0xf3, 0xe6, 0xb0, 0x40, - 0x9e, 0xb8, 0x9d, 0x78, 0x5f, 0x63, 0xac, 0xd1, 0x3d, 0xb0, 0xa0, 0x5e, - 0x9e, 0x4f, 0x4e, 0xbf, 0x24, 0xe0, 0xc6, 0x8e, 0xbf, 0xe0, 0x73, 0x17, - 0x91, 0xdd, 0x8e, 0xbf, 0x7f, 0xf0, 0xdd, 0x1d, 0x7f, 0xe0, 0xe6, 0xe0, - 0x9d, 0xcc, 0x86, 0x4e, 0xad, 0xcf, 0xa2, 0x71, 0x3d, 0xce, 0xd3, 0xa9, - 0xd1, 0xb5, 0x90, 0xa0, 0xe9, 0x2d, 0xff, 0x3e, 0xbc, 0xe7, 0x73, 0x19, - 0x3a, 0xff, 0x67, 0x5b, 0xee, 0x63, 0x27, 0x5f, 0x37, 0xcf, 0x1c, 0xeb, - 0xdd, 0x76, 0x9d, 0x50, 0x6f, 0xa7, 0x11, 0xdf, 0xce, 0xbc, 0x4e, 0xb2, - 0x75, 0xfb, 0x01, 0xc7, 0xe1, 0xd7, 0xdd, 0x46, 0x15, 0xce, 0xb6, 0x84, - 0xf2, 0xf4, 0x4d, 0x4e, 0x99, 0x8a, 0x38, 0xf0, 0x8a, 0x1d, 0xef, 0xff, - 0x3a, 0xdd, 0xa0, 0x17, 0xe4, 0x67, 0x4e, 0xa3, 0xa9, 0xa7, 0xa1, 0x3c, - 0x8d, 0x7f, 0xa4, 0x39, 0x38, 0x73, 0x47, 0x5f, 0xf6, 0xed, 0x8c, 0x1c, - 0xfe, 0x8e, 0xad, 0xd1, 0x1d, 0xc2, 0x51, 0x32, 0xb4, 0xf1, 0xd7, 0x37, - 0x47, 0x5a, 0x1a, 0x6a, 0x77, 0x13, 0xbf, 0x9f, 0x3e, 0x82, 0xc1, 0x55, - 0x07, 0xa5, 0xe9, 0x3d, 0xff, 0xec, 0xfb, 0xb1, 0xe7, 0x6d, 0x62, 0xdd, - 0x5c, 0xeb, 0xff, 0xb9, 0x09, 0xf6, 0xe2, 0x83, 0x9e, 0x9d, 0x7e, 0x16, - 0x5f, 0x8e, 0x75, 0xfb, 0x39, 0xbc, 0x2b, 0x9d, 0x7d, 0xee, 0x9c, 0x4e, - 0xbf, 0xdd, 0xe4, 0x26, 0x92, 0x71, 0xd4, 0xe7, 0xa9, 0x84, 0x34, 0x89, - 0x83, 0xc2, 0x18, 0x93, 0x69, 0xfa, 0xfe, 0x61, 0xfb, 0xd8, 0x64, 0xeb, - 0xff, 0x06, 0x3b, 0x8b, 0x49, 0xe7, 0x59, 0xd7, 0xdf, 0x7d, 0xda, 0x75, - 0xfc, 0x9e, 0xcf, 0x0a, 0x7a, 0x75, 0x6c, 0x7a, 0x5d, 0x22, 0xa7, 0x47, - 0x16, 0x17, 0x44, 0x24, 0x6f, 0xe9, 0xdd, 0x87, 0x49, 0xe3, 0xad, 0x87, - 0x52, 0xcd, 0xf8, 0x98, 0x5f, 0xe0, 0x78, 0x07, 0x98, 0xef, 0x4e, 0xbf, - 0xe7, 0x40, 0x7c, 0x63, 0x7d, 0x1d, 0x4e, 0x7d, 0xc2, 0x6f, 0x4a, 0xcb, - 0x2e, 0x6e, 0x7c, 0x19, 0x56, 0xe4, 0x87, 0x7e, 0x01, 0x16, 0x46, 0x0e, - 0xa2, 0x54, 0x9a, 0xf7, 0x84, 0x0a, 0x13, 0xb2, 0x3f, 0xd8, 0xc0, 0x96, - 0x67, 0xc8, 0xda, 0xa2, 0x31, 0x9f, 0x61, 0x56, 0x24, 0x5a, 0x8d, 0x5b, - 0xf1, 0x8e, 0x85, 0xc7, 0xcc, 0x23, 0xaf, 0xfe, 0xe2, 0x3f, 0xf9, 0x0a, - 0x60, 0xfa, 0x75, 0xfd, 0x9f, 0x74, 0x5e, 0x8e, 0xbd, 0xaf, 0x3a, 0x3a, - 0xff, 0xfb, 0x37, 0x6f, 0xc3, 0xb4, 0xdc, 0x85, 0xa6, 0x8e, 0xbf, 0xe0, - 0xc6, 0x01, 0x37, 0x18, 0x3a, 0xf7, 0xc5, 0xce, 0xbb, 0x93, 0x62, 0x65, - 0xcc, 0xa1, 0xc1, 0x58, 0x8f, 0x69, 0x4b, 0xc9, 0xb5, 0x4c, 0xab, 0xd9, - 0xe5, 0x48, 0xdf, 0xd9, 0xd9, 0x44, 0x48, 0xd1, 0x66, 0xdf, 0x95, 0x4d, - 0xc7, 0xe1, 0xd5, 0x31, 0xf1, 0x41, 0xc5, 0xfe, 0x5c, 0xce, 0x8b, 0xf3, - 0xd3, 0xae, 0xc0, 0x1d, 0x7f, 0xe8, 0x6c, 0xd9, 0xd9, 0x44, 0x48, 0xd1, - 0x40, 0x5f, 0xe4, 0x5b, 0xab, 0xf3, 0x36, 0x3a, 0xd3, 0x62, 0x25, 0x16, - 0x2b, 0xc4, 0xab, 0xfa, 0x3f, 0xa6, 0xa7, 0xa7, 0x5f, 0xcd, 0x9b, 0x19, - 0x76, 0x9d, 0x53, 0x1e, 0xdb, 0x96, 0xdc, 0x1e, 0x1d, 0x7f, 0x69, 0xd6, - 0x2e, 0xc9, 0xd6, 0xe1, 0xd7, 0xbc, 0x8b, 0x27, 0x5d, 0x9f, 0xc3, 0x5d, - 0xe8, 0x85, 0x7a, 0x88, 0x61, 0x5a, 0xbb, 0xc6, 0x8e, 0xbc, 0x10, 0x61, - 0xd7, 0xfb, 0x3b, 0xf1, 0x75, 0xe8, 0xeb, 0x4f, 0x1d, 0x48, 0x7b, 0xfc, - 0x1b, 0xf4, 0xc6, 0xfa, 0x51, 0x12, 0x34, 0x5b, 0xf7, 0xf7, 0x9f, 0xc4, - 0xa3, 0xa7, 0x57, 0x4f, 0x6f, 0xd2, 0xdb, 0xec, 0x14, 0x64, 0xeb, 0xf7, - 0xdb, 0xaf, 0x3a, 0x3a, 0xf6, 0xb8, 0x03, 0xaf, 0xde, 0x7e, 0x2f, 0xe9, - 0xd4, 0xb3, 0xc5, 0x9c, 0x39, 0x7f, 0xf7, 0xf4, 0x9a, 0x71, 0xcf, 0xf1, - 0x0e, 0xbc, 0x39, 0xc3, 0xa9, 0x67, 0xb7, 0x39, 0x06, 0xfc, 0x07, 0x57, - 0x0a, 0xce, 0xbf, 0xe8, 0xd3, 0xe0, 0x83, 0x8e, 0x75, 0xff, 0xd8, 0xbe, - 0xe6, 0xfc, 0x18, 0x57, 0xd8, 0xeb, 0xb5, 0xae, 0x9f, 0xe0, 0x9a, 0xd3, - 0xa6, 0xed, 0x8f, 0xe8, 0x49, 0x10, 0xa6, 0xbe, 0x84, 0x1f, 0x9d, 0x7b, - 0xaf, 0xf3, 0xaf, 0xe6, 0x60, 0x1c, 0x45, 0x9d, 0x7f, 0x7d, 0x30, 0x0e, - 0xb3, 0xab, 0xe7, 0xb0, 0xc1, 0x6d, 0xda, 0x13, 0xaf, 0xed, 0xf4, 0xf2, - 0xc5, 0x9d, 0x5d, 0x46, 0xc4, 0x39, 0xe8, 0x8c, 0x22, 0xb7, 0xdc, 0x50, - 0x0b, 0x3a, 0xfb, 0x6e, 0xe0, 0x0e, 0xb3, 0x4e, 0xa7, 0x36, 0x58, 0x45, - 0x58, 0x7e, 0x82, 0xab, 0x53, 0xe2, 0xef, 0x73, 0xc2, 0x71, 0xa4, 0x60, - 0x77, 0xc8, 0x45, 0x21, 0x1f, 0x48, 0x39, 0x1f, 0x2f, 0xa7, 0xe3, 0x0f, - 0x7f, 0xc2, 0xc2, 0xfe, 0x8d, 0xe6, 0x5c, 0x7c, 0xea, 0x99, 0x1c, 0xa3, - 0x0b, 0x7b, 0x95, 0xa9, 0xf0, 0xeb, 0xcb, 0x8d, 0xce, 0xbe, 0xef, 0x73, - 0xc9, 0xd7, 0xf2, 0x6b, 0x6c, 0x62, 0x65, 0x64, 0xf7, 0xdc, 0x82, 0x07, - 0x2f, 0xdd, 0x94, 0x44, 0x8d, 0x14, 0xa5, 0xff, 0xf4, 0x7c, 0x73, 0x6e, - 0xbf, 0x13, 0x99, 0xd3, 0xaf, 0x43, 0x66, 0xc4, 0x40, 0x7a, 0x67, 0x7f, - 0xcd, 0x9b, 0x3b, 0x28, 0x89, 0x1a, 0x24, 0xeb, 0x4c, 0xb3, 0xfa, 0x83, - 0x5a, 0x77, 0xf5, 0x7b, 0xda, 0x58, 0xe3, 0x57, 0xc1, 0x7a, 0x8b, 0x59, - 0x0b, 0xb9, 0x46, 0x76, 0x90, 0x82, 0x57, 0x85, 0x03, 0x24, 0xfd, 0x85, - 0xb2, 0xe9, 0xd6, 0x5c, 0x84, 0x74, 0x11, 0x7b, 0x0c, 0x91, 0x84, 0x8e, - 0xa7, 0xbd, 0x7f, 0x08, 0x79, 0xd1, 0xa8, 0xdf, 0xbb, 0x28, 0x89, 0x1a, - 0x21, 0xfb, 0xff, 0x43, 0x66, 0xce, 0xca, 0x22, 0x46, 0x89, 0x4e, 0xd3, - 0x61, 0xfe, 0xac, 0xce, 0xff, 0x4d, 0x9d, 0x94, 0x44, 0x8d, 0x11, 0x3d, - 0xfc, 0xca, 0x7f, 0x41, 0x59, 0xd7, 0xee, 0xca, 0x22, 0x46, 0x88, 0xc6, - 0xd3, 0x39, 0xf0, 0xe1, 0x75, 0xff, 0xe9, 0x97, 0x0d, 0x9b, 0x3b, 0x28, - 0x89, 0x1a, 0x27, 0x9b, 0xfa, 0x6f, 0x5c, 0x5b, 0xa3, 0xa9, 0xd3, 0x74, - 0xd8, 0xa1, 0xb0, 0xa0, 0xe1, 0x3f, 0xd5, 0xef, 0xdd, 0x94, 0x44, 0x8d, - 0x11, 0x05, 0xff, 0xa1, 0xb3, 0x67, 0x65, 0x11, 0x23, 0x44, 0xa9, 0x69, - 0xb0, 0xff, 0x56, 0x67, 0x7f, 0xa6, 0xce, 0xca, 0x22, 0x46, 0x88, 0xa2, - 0xff, 0x4d, 0x9d, 0x94, 0x44, 0x8d, 0x11, 0x95, 0xff, 0xe9, 0x97, 0x0d, - 0x9b, 0x3b, 0x28, 0x89, 0x1a, 0x26, 0x5b, 0xfd, 0x36, 0x76, 0x51, 0x12, - 0x34, 0x54, 0x97, 0xfa, 0x6c, 0xec, 0xa2, 0x24, 0x68, 0xae, 0xaf, 0xf4, - 0xd9, 0xd9, 0x44, 0x48, 0xd1, 0x62, 0xdf, 0xfc, 0xb8, 0x6c, 0xd9, 0xd9, - 0x44, 0x48, 0xd1, 0x3d, 0x5f, 0xf3, 0x13, 0x43, 0xa4, 0xf2, 0x2a, 0x3a, - 0xff, 0xfc, 0xc8, 0xba, 0xe6, 0xcd, 0x23, 0x00, 0x88, 0x50, 0xeb, 0xff, - 0x07, 0x5c, 0x86, 0xcd, 0x3e, 0x6b, 0xe7, 0x5f, 0xb3, 0xfa, 0x45, 0x9d, - 0x7f, 0xf9, 0xf7, 0xfe, 0x32, 0x9d, 0xfe, 0x82, 0xae, 0x75, 0xe8, 0xde, - 0x61, 0x3f, 0x4f, 0x93, 0x5b, 0xf8, 0x9a, 0x1f, 0x55, 0xb5, 0x0b, 0x9a, - 0x99, 0x50, 0x5b, 0xa8, 0x24, 0x70, 0x17, 0xf4, 0xfa, 0x9c, 0x18, 0x64, - 0xeb, 0xf6, 0x7d, 0x03, 0xa3, 0xae, 0x56, 0x55, 0xb8, 0xea, 0x56, 0xe3, - 0xc8, 0x56, 0x24, 0xd7, 0xfd, 0x3f, 0xf9, 0x1c, 0xef, 0x5e, 0x47, 0x5f, - 0x75, 0x7f, 0xdc, 0xeb, 0xd2, 0xce, 0x15, 0x79, 0x6f, 0xa3, 0xaf, 0xfd, - 0x1a, 0xf1, 0xad, 0x63, 0x5a, 0xe7, 0x5f, 0xff, 0x86, 0x14, 0x4e, 0xbb, - 0x5b, 0x9a, 0xf7, 0xd7, 0x3a, 0x94, 0x44, 0xa7, 0x0f, 0xef, 0xff, 0xee, - 0xa2, 0xa8, 0x5c, 0xcf, 0xde, 0xa2, 0xa9, 0x07, 0x63, 0xaf, 0x93, 0x9e, - 0x56, 0x75, 0xff, 0xe4, 0x53, 0xc6, 0x0c, 0x6f, 0xa5, 0x14, 0x83, 0xaa, - 0x47, 0xe0, 0x24, 0x77, 0xff, 0xa3, 0x43, 0x9e, 0xcd, 0xc4, 0x94, 0x74, - 0xeb, 0xf8, 0x18, 0xa7, 0xf2, 0x47, 0x5f, 0x71, 0xd7, 0x23, 0xaa, 0x0f, - 0x3b, 0xe5, 0xb7, 0xe0, 0x23, 0x28, 0xc1, 0xd7, 0xff, 0x78, 0x77, 0x17, - 0x5f, 0x8f, 0x1c, 0x9e, 0x3a, 0x9c, 0xfc, 0xc4, 0xa2, 0xff, 0xdc, 0xc6, - 0x78, 0x9c, 0x7e, 0xb9, 0xd7, 0x46, 0xe7, 0x5f, 0xe8, 0xd4, 0x70, 0x23, - 0xb1, 0xd4, 0x27, 0x90, 0x11, 0x6a, 0xd9, 0x5d, 0xaa, 0x42, 0xbf, 0xa4, - 0x8b, 0x86, 0x87, 0x08, 0x46, 0x12, 0xff, 0x84, 0xa7, 0x92, 0x05, 0x50, - 0x85, 0xbc, 0x31, 0xf3, 0xaf, 0x0a, 0x68, 0xeb, 0x31, 0x3e, 0x9b, 0x47, - 0x1a, 0xbe, 0xec, 0xe8, 0x59, 0xd7, 0xe5, 0x8c, 0x7f, 0x47, 0x5f, 0x9b, - 0xc7, 0xce, 0x9d, 0x5b, 0x9e, 0x67, 0x49, 0xab, 0x11, 0x7c, 0x85, 0x81, - 0x6f, 0xbf, 0xee, 0x47, 0xdd, 0x9d, 0x22, 0xce, 0xbf, 0xce, 0xd1, 0xcd, - 0xff, 0x87, 0x5e, 0xe0, 0x56, 0x75, 0x22, 0x21, 0x7a, 0x70, 0x13, 0x1b, - 0xf0, 0xa8, 0x99, 0xa3, 0xaf, 0xcc, 0x47, 0xe2, 0x47, 0x5f, 0xfd, 0x8c, - 0x47, 0xb9, 0x2e, 0x47, 0xba, 0x3a, 0xff, 0xda, 0x8d, 0xdc, 0x60, 0x18, - 0xa1, 0xd4, 0x88, 0xcf, 0xe1, 0x30, 0x93, 0xfd, 0x16, 0xf2, 0xdf, 0x87, - 0x5f, 0x08, 0x3c, 0x28, 0x75, 0xfd, 0x9a, 0x62, 0x07, 0x63, 0xab, 0x0f, - 0xb2, 0x06, 0xc4, 0x92, 0xfc, 0x15, 0x34, 0x07, 0x3a, 0xfe, 0x7d, 0xdb, - 0xa4, 0x13, 0xab, 0x13, 0x27, 0x48, 0x53, 0xf0, 0xb0, 0x4a, 0x2f, 0xff, - 0xfc, 0x9d, 0xeb, 0xf9, 0xfa, 0x08, 0x5b, 0x9a, 0x00, 0x63, 0xad, 0x3a, - 0xff, 0xfe, 0x1c, 0x53, 0x07, 0xc6, 0xbf, 0xcc, 0x5f, 0x97, 0xf4, 0xeb, - 0x71, 0xd1, 0x95, 0x8d, 0x97, 0xd1, 0xbf, 0xd6, 0x75, 0xfb, 0x60, 0x75, - 0x18, 0x3a, 0xfe, 0x04, 0x77, 0xd9, 0xec, 0x3a, 0xf9, 0xbc, 0xf3, 0x38, - 0xeb, 0xff, 0x0a, 0x37, 0xfc, 0xce, 0xa6, 0x8e, 0xbf, 0xf4, 0x67, 0xae, - 0x30, 0x0c, 0x50, 0xea, 0x69, 0xfc, 0x7a, 0x79, 0x7f, 0xa3, 0x7d, 0x7f, - 0xf8, 0xae, 0x75, 0xff, 0xe7, 0xcd, 0xff, 0xc7, 0xf8, 0xbf, 0xba, 0x3a, - 0xf6, 0xb8, 0xb3, 0xab, 0xe7, 0xca, 0x14, 0x9b, 0xdb, 0x27, 0x4e, 0xbf, - 0x83, 0xaf, 0xeb, 0x3e, 0x75, 0xe6, 0x18, 0x60, 0xab, 0xff, 0xdf, 0x4f, - 0xeb, 0x89, 0x3d, 0xe7, 0xae, 0xd2, 0xa6, 0x2f, 0xe9, 0x44, 0x63, 0x20, - 0xe0, 0x53, 0x2f, 0xff, 0xf9, 0x3e, 0xd7, 0x1c, 0xff, 0x13, 0x3e, 0xeb, - 0x4e, 0xb4, 0xea, 0x6a, 0xb7, 0x80, 0x13, 0xe1, 0x12, 0x14, 0xb2, 0x61, - 0xd8, 0x4f, 0x2c, 0x8c, 0x61, 0x37, 0xf8, 0x74, 0x4e, 0x30, 0xbf, 0xed, - 0xdb, 0xad, 0x60, 0x23, 0xe7, 0x5b, 0x0e, 0xa7, 0x3c, 0x85, 0x0e, 0x6d, - 0x07, 0x5e, 0x7e, 0x68, 0xea, 0xdc, 0xd5, 0x20, 0x7d, 0xff, 0xfd, 0x1f, - 0x4e, 0x42, 0xfc, 0x66, 0x9f, 0x3b, 0x82, 0x75, 0x93, 0xa7, 0xf2, 0x24, - 0x37, 0xdf, 0x7d, 0xd8, 0x3a, 0xb8, 0x79, 0x2c, 0x13, 0x5c, 0xc7, 0x0e, - 0xbf, 0xfc, 0xe3, 0x2f, 0x3d, 0x8f, 0x53, 0xfc, 0x73, 0xaf, 0xf2, 0x31, - 0xac, 0xc1, 0xd8, 0xeb, 0xe7, 0xd3, 0xce, 0x3a, 0xff, 0xe7, 0x18, 0xfb, - 0x5d, 0x48, 0x63, 0xe7, 0x57, 0x0f, 0x94, 0x24, 0x57, 0xbc, 0x44, 0x8e, - 0xa9, 0x26, 0x6f, 0xe8, 0xbe, 0x92, 0xbf, 0x09, 0x75, 0x44, 0x57, 0xcb, - 0xf2, 0xe2, 0x75, 0xfc, 0xc2, 0x91, 0x03, 0xe9, 0xd7, 0x05, 0x67, 0x52, - 0x1e, 0x27, 0x0b, 0xaf, 0xf3, 0xc7, 0x78, 0xc4, 0x00, 0xab, 0x98, 0x60, - 0xaa, 0x01, 0xe5, 0x30, 0x65, 0x7b, 0xe8, 0xae, 0x54, 0xc6, 0x8e, 0xfe, - 0xde, 0x49, 0xae, 0x21, 0xd7, 0xc1, 0x68, 0x7e, 0x75, 0x22, 0x6e, 0x4c, - 0xb3, 0x6a, 0x11, 0xdf, 0x2f, 0x9e, 0x2d, 0xb9, 0x8d, 0x1d, 0x6c, 0x3a, - 0xdb, 0xe1, 0xa6, 0xf8, 0xbd, 0xf6, 0xed, 0x9f, 0x77, 0x3a, 0xff, 0xed, - 0x68, 0x02, 0xe0, 0xe3, 0xff, 0x47, 0x53, 0xa2, 0x4f, 0x09, 0xc2, 0x53, - 0x7f, 0xef, 0xa7, 0x63, 0xd5, 0x5f, 0xce, 0x1d, 0x7f, 0xc8, 0xc0, 0xe7, - 0xd0, 0x3e, 0x9d, 0x7f, 0xa3, 0xbf, 0xd0, 0xa2, 0x87, 0x5f, 0xfe, 0xd6, - 0x29, 0x81, 0xec, 0x01, 0xf8, 0xe7, 0x53, 0x53, 0x20, 0x42, 0xe5, 0x74, - 0x08, 0x38, 0xd1, 0x95, 0xec, 0x4e, 0x9d, 0x7f, 0x9a, 0x8b, 0xe6, 0xf0, - 0xae, 0x75, 0xf4, 0x75, 0xda, 0x75, 0x6c, 0x7e, 0x1b, 0x8d, 0x2c, 0xda, - 0xfb, 0x8a, 0xe8, 0xb3, 0xaf, 0x0b, 0xfa, 0x75, 0xe7, 0x5e, 0x78, 0x37, - 0xfa, 0x24, 0xbf, 0xf3, 0xef, 0xc7, 0x5c, 0xb8, 0x8c, 0x9d, 0x58, 0x8e, - 0x24, 0x70, 0xe9, 0x9d, 0xfa, 0x51, 0xb6, 0x30, 0x75, 0xf9, 0xfa, 0x0c, - 0x13, 0xa8, 0x4f, 0x37, 0xe5, 0x17, 0xff, 0x3f, 0xaf, 0xc5, 0x8c, 0x29, - 0xc4, 0x3a, 0xd3, 0xf9, 0xd7, 0xf8, 0x1c, 0x71, 0x62, 0x37, 0x3a, 0xff, - 0xe4, 0x07, 0x1e, 0x4f, 0xec, 0x0f, 0xa7, 0x5f, 0xff, 0xf2, 0xe0, 0x77, - 0x6c, 0xcc, 0x62, 0x4e, 0xc1, 0xc0, 0x43, 0x4f, 0x17, 0xad, 0xf7, 0xc4, - 0x3b, 0x1d, 0x48, 0x89, 0x61, 0x74, 0xa7, 0x4e, 0x9b, 0xa4, 0x2b, 0x43, - 0x81, 0x5d, 0x19, 0x86, 0x1b, 0x37, 0xcd, 0x9f, 0xd5, 0x99, 0xf0, 0xeb, - 0xe4, 0x18, 0x01, 0xd7, 0xb6, 0x5a, 0x1d, 0x40, 0x37, 0x62, 0x3f, 0x5b, - 0xa2, 0x31, 0x1b, 0x2f, 0xff, 0xb3, 0xfa, 0xc6, 0x78, 0xf3, 0xb3, 0x9c, - 0x73, 0xaf, 0xff, 0xff, 0xc9, 0x9b, 0xe9, 0x31, 0x8f, 0x19, 0xbb, 0x74, - 0x9f, 0xd2, 0x6e, 0x00, 0x07, 0x63, 0xaf, 0xff, 0xc8, 0x20, 0xf1, 0xe7, - 0xe9, 0xa8, 0x41, 0x0b, 0x4e, 0xa1, 0x4c, 0xbb, 0xea, 0x13, 0xa1, 0x11, - 0x7f, 0xb6, 0x8f, 0xfb, 0xe4, 0x5a, 0x75, 0xe5, 0x30, 0x07, 0x5f, 0xdc, - 0x8e, 0xc9, 0xfe, 0x75, 0xd0, 0x03, 0xaf, 0xee, 0xc6, 0xb9, 0x0d, 0x3a, - 0xdb, 0x9d, 0x72, 0x30, 0x75, 0xde, 0x7d, 0x3a, 0x99, 0x35, 0xfe, 0x8b, - 0x5e, 0x6c, 0x00, 0xeb, 0x98, 0x60, 0xea, 0x6a, 0x35, 0xf0, 0x56, 0x45, - 0x88, 0x81, 0xa2, 0x36, 0x06, 0xef, 0x7f, 0xcf, 0xa5, 0x4c, 0x7a, 0xd7, - 0xff, 0xfd, 0xc0, 0xc2, 0x8b, 0x80, 0x66, 0x0a, 0x9a, 0xd6, 0x0f, 0xa7, - 0x5f, 0xff, 0xcd, 0x8d, 0x69, 0xf3, 0x60, 0xb4, 0x1d, 0x18, 0x60, 0xeb, - 0xbe, 0xe0, 0x46, 0x0a, 0x33, 0x53, 0x55, 0x4a, 0x00, 0x73, 0x78, 0xd6, - 0x52, 0x1e, 0x57, 0xfd, 0x9f, 0xe3, 0xf7, 0xf9, 0x23, 0xaf, 0x3f, 0x59, - 0x3a, 0x9d, 0x73, 0xbf, 0x23, 0x51, 0x43, 0x78, 0x95, 0x94, 0x29, 0x53, - 0xc6, 0xf7, 0xb5, 0x0c, 0x9d, 0x7d, 0x9f, 0x85, 0x47, 0x56, 0xe6, 0xf8, - 0x47, 0x2f, 0xb3, 0x7d, 0xa7, 0x1d, 0x7f, 0xc2, 0x0c, 0x10, 0xb7, 0x34, - 0x75, 0x74, 0xf6, 0xe0, 0x96, 0xf9, 0xf3, 0xc8, 0x0e, 0xbf, 0xca, 0x27, - 0xe3, 0x8c, 0x2b, 0x9d, 0x7f, 0xdd, 0xc6, 0x79, 0x9a, 0x81, 0x3a, 0xff, - 0xb9, 0x8d, 0xc0, 0xcf, 0xd0, 0x27, 0x5f, 0xff, 0xe4, 0x1c, 0xdf, 0xea, - 0x47, 0xf8, 0xfc, 0xc9, 0xd0, 0xd3, 0xaa, 0x49, 0x96, 0x21, 0x17, 0x4d, - 0xfe, 0x6f, 0x38, 0xee, 0xff, 0xcf, 0xa8, 0xe2, 0x02, 0x49, 0xb1, 0xd5, - 0x88, 0x89, 0x0a, 0x65, 0xe7, 0x1f, 0x9d, 0x7f, 0x93, 0x89, 0xd6, 0xb2, - 0xe7, 0x5f, 0x47, 0x5d, 0xa7, 0x5f, 0xff, 0xc8, 0x30, 0x83, 0xef, 0x5f, - 0x90, 0x9f, 0x7e, 0x1d, 0x42, 0x7e, 0xdf, 0x20, 0xbf, 0x27, 0xf4, 0x1d, - 0x8e, 0xbf, 0xfe, 0x71, 0x4f, 0x7f, 0xbc, 0x93, 0xbe, 0x5c, 0x07, 0x52, - 0x22, 0x69, 0x64, 0x3f, 0x28, 0xbf, 0x74, 0x32, 0xe3, 0x9d, 0x7f, 0x75, - 0x96, 0xa7, 0xf4, 0x75, 0x85, 0xcf, 0x57, 0x09, 0xef, 0xfb, 0x19, 0x86, - 0x63, 0x76, 0xe8, 0xeb, 0xfd, 0x9b, 0x60, 0xed, 0x8c, 0x1d, 0x7e, 0x7e, - 0xf7, 0x38, 0x75, 0xfc, 0x30, 0xa3, 0xad, 0xce, 0xa6, 0x9e, 0x88, 0x49, - 0xaf, 0x9f, 0x65, 0x14, 0x3a, 0xe4, 0x9c, 0x75, 0xb8, 0x75, 0x2b, 0x9a, - 0x70, 0x8b, 0xde, 0x03, 0xac, 0xeb, 0xfd, 0x9e, 0xe3, 0x2f, 0xbe, 0x8e, - 0xa7, 0x3c, 0xfc, 0x1b, 0xbf, 0xb9, 0x0d, 0x7d, 0x34, 0xeb, 0xfe, 0xce, - 0x26, 0xfa, 0xe0, 0x74, 0x75, 0xd8, 0x32, 0x3e, 0x5f, 0x4b, 0x2f, 0xe1, - 0x8f, 0x41, 0x82, 0x75, 0xfc, 0xb4, 0x9e, 0xce, 0xa8, 0x75, 0xe6, 0x18, - 0x60, 0xab, 0xff, 0x9f, 0xa2, 0x18, 0xf3, 0x8c, 0xba, 0xce, 0x98, 0xbf, - 0xa7, 0x5d, 0x23, 0x68, 0xd6, 0x46, 0x84, 0xaf, 0x08, 0x46, 0x49, 0x7a, - 0x74, 0xb8, 0x42, 0x70, 0x8a, 0x12, 0xc5, 0xcf, 0x50, 0x85, 0xf9, 0x68, - 0x4a, 0xd8, 0x4f, 0xbe, 0xef, 0x73, 0x87, 0x5f, 0xdc, 0x45, 0x4a, 0x82, - 0xa1, 0xd4, 0xe7, 0xa7, 0x22, 0x1b, 0x4f, 0xc7, 0x59, 0x0e, 0xbf, 0xef, - 0xbf, 0x75, 0xc7, 0x1f, 0x9d, 0x69, 0xf8, 0xeb, 0xfe, 0xfb, 0xf7, 0x5c, - 0x71, 0xf9, 0xd7, 0x69, 0xce, 0xbc, 0xb0, 0x39, 0xd7, 0xf8, 0x7f, 0x0c, - 0xe9, 0xfe, 0x75, 0x21, 0xe6, 0xc0, 0xdd, 0xf2, 0x46, 0x48, 0xeb, 0xff, - 0x64, 0xe1, 0xcd, 0x32, 0x2e, 0x03, 0xaf, 0xa4, 0x07, 0xd8, 0xeb, 0xbd, - 0x73, 0xaf, 0x69, 0x3a, 0x75, 0x61, 0xe9, 0xfa, 0x45, 0xf1, 0x6b, 0xfc, - 0xdc, 0x14, 0x06, 0x09, 0xd7, 0xbf, 0xa9, 0x9d, 0x3d, 0xcc, 0x15, 0x64, - 0xdf, 0x8c, 0x5e, 0x90, 0x08, 0xfe, 0xa1, 0x23, 0xf2, 0xfb, 0xb4, 0xe7, - 0x5e, 0x58, 0x1c, 0xeb, 0xfc, 0x3f, 0x86, 0x74, 0xff, 0x3a, 0x90, 0xf3, - 0x60, 0x6e, 0xf9, 0x23, 0x24, 0x75, 0xff, 0xb2, 0x70, 0xe6, 0x99, 0x17, - 0x01, 0xd7, 0xd2, 0x03, 0xec, 0x75, 0xfc, 0xcf, 0xa8, 0xaf, 0x0c, 0x9d, - 0x77, 0xae, 0x75, 0xed, 0x27, 0x4e, 0xac, 0x44, 0x2c, 0x88, 0xbd, 0x32, - 0xf8, 0xb5, 0xfe, 0x6e, 0x0a, 0x03, 0x04, 0xeb, 0xf8, 0x60, 0x18, 0xa4, - 0xce, 0xb9, 0x20, 0x01, 0x5c, 0x0f, 0x94, 0xa1, 0x36, 0x61, 0x13, 0xc6, - 0x2f, 0x48, 0x04, 0x7f, 0x50, 0xc3, 0xf9, 0xed, 0xff, 0xdd, 0x7d, 0xf4, - 0x2e, 0xbc, 0xdf, 0xe7, 0x5f, 0xff, 0xa0, 0x19, 0x82, 0xa7, 0x91, 0x71, - 0xd9, 0x3a, 0x75, 0xe8, 0xee, 0xc7, 0x90, 0x4a, 0xf9, 0xb9, 0xbb, 0x4f, - 0x20, 0x95, 0xed, 0x20, 0x0f, 0x20, 0x95, 0xcc, 0x30, 0x79, 0x04, 0xaa, - 0x48, 0xa5, 0x64, 0xa7, 0xe5, 0xec, 0x14, 0x5d, 0x1f, 0x2c, 0x82, 0x49, - 0x8d, 0xfd, 0xfd, 0x9c, 0xcc, 0x15, 0x0e, 0xbd, 0x03, 0xef, 0x85, 0xf4, - 0xd7, 0x9c, 0xb1, 0xec, 0x30, 0x56, 0x88, 0x31, 0x9c, 0x7c, 0xd2, 0xfa, - 0x7b, 0x23, 0x87, 0x5b, 0x15, 0xd1, 0x43, 0xeb, 0xf5, 0x9a, 0x75, 0xfe, - 0x65, 0xa1, 0xdb, 0xe9, 0xb1, 0x57, 0xf9, 0x1a, 0x18, 0xd7, 0x10, 0xeb, - 0xfb, 0x27, 0x42, 0xf3, 0x87, 0x59, 0xa5, 0x5e, 0x8e, 0xec, 0x55, 0x15, - 0x4e, 0x6d, 0xa4, 0x20, 0xb1, 0xcb, 0xcf, 0xec, 0x8a, 0x98, 0xd6, 0xd2, - 0xd1, 0x7a, 0x30, 0x90, 0xa7, 0x4c, 0x57, 0x21, 0xdd, 0x7c, 0x18, 0xeb, - 0x4e, 0xb2, 0xce, 0xbb, 0x1a, 0x03, 0x62, 0xc9, 0x0d, 0xf9, 0x8c, 0x65, - 0x16, 0x75, 0xfd, 0x27, 0x65, 0xaf, 0xe9, 0x56, 0x43, 0xaf, 0xfb, 0x60, - 0xb4, 0x1c, 0x0c, 0x09, 0xd7, 0xf2, 0x3a, 0xf6, 0xc6, 0x0e, 0xbf, 0x66, - 0xcb, 0xc5, 0x9d, 0x7b, 0x49, 0xd3, 0xa8, 0x4f, 0x0b, 0xe4, 0xf7, 0xf0, - 0xc7, 0xbe, 0x87, 0x47, 0x5f, 0xc8, 0xa7, 0x97, 0x5c, 0xc0, 0x4c, 0x1b, - 0x03, 0xfa, 0x73, 0xa6, 0xff, 0x90, 0xd6, 0x27, 0x98, 0x85, 0x03, 0x19, - 0xa5, 0xf0, 0xe6, 0xc1, 0x3a, 0x9a, 0xb8, 0x5a, 0x02, 0xcc, 0x10, 0xe4, - 0x69, 0x62, 0xb1, 0xa8, 0xfe, 0x7e, 0x69, 0x7f, 0xfe, 0xdb, 0xbd, 0xc0, - 0x42, 0xf9, 0x1f, 0x17, 0x64, 0xeb, 0xff, 0xff, 0xc1, 0xe8, 0x59, 0x18, - 0xf7, 0x5a, 0xc5, 0x30, 0x3d, 0x80, 0x3f, 0x1c, 0xeb, 0xe5, 0x5c, 0x0f, - 0x93, 0xaf, 0x30, 0xc3, 0x05, 0x5c, 0xd7, 0x2a, 0x62, 0xfe, 0x9d, 0x33, - 0x7d, 0x95, 0x77, 0x78, 0xea, 0x2d, 0xfc, 0xa3, 0xf7, 0xb9, 0xc3, 0xaf, - 0xed, 0x99, 0x6c, 0xff, 0xdd, 0x8e, 0xbe, 0xe4, 0x6e, 0xc1, 0xd7, 0xed, - 0xba, 0x8e, 0xb3, 0xaf, 0xff, 0x9f, 0xcf, 0xc5, 0xfd, 0x8f, 0xfb, 0xe4, - 0x5a, 0x75, 0x2b, 0x48, 0xd3, 0x43, 0x68, 0x23, 0xf9, 0x3d, 0xef, 0x20, - 0x64, 0xeb, 0xcd, 0x41, 0x3a, 0xfb, 0x6f, 0x2a, 0x98, 0x3a, 0xff, 0xfe, - 0x0c, 0x6d, 0x20, 0xed, 0xfc, 0xe0, 0xe7, 0xf8, 0x87, 0x5f, 0x9d, 0x91, - 0x0e, 0x8e, 0xae, 0x22, 0x0b, 0xeb, 0x77, 0xf4, 0x0f, 0xb9, 0xf5, 0x0e, - 0xad, 0x93, 0x33, 0x68, 0xfc, 0x0d, 0x7e, 0x15, 0x53, 0xc4, 0x77, 0x46, - 0x8e, 0xb8, 0x33, 0xf1, 0xd4, 0x26, 0xc0, 0x22, 0xb7, 0x44, 0xd3, 0xeb, - 0xb9, 0x10, 0x9f, 0x1e, 0x67, 0xf2, 0xf5, 0x6c, 0x7c, 0xac, 0x08, 0xde, - 0x5e, 0x86, 0xd1, 0xc7, 0x36, 0x16, 0x60, 0x94, 0x4b, 0x93, 0x90, 0x4a, - 0x43, 0x92, 0x51, 0x87, 0x6f, 0x1a, 0xd2, 0x47, 0x8a, 0xcc, 0xa2, 0xce, - 0xc7, 0x3c, 0xb9, 0x44, 0x3c, 0x9d, 0xd6, 0x88, 0x51, 0xfa, 0xf8, 0x31, - 0xeb, 0x6a, 0x75, 0x17, 0xf4, 0xd4, 0x60, 0xc7, 0x50, 0xc1, 0xfc, 0xf4, - 0x60, 0x1e, 0x63, 0x73, 0x55, 0x08, 0x3b, 0xf2, 0xf1, 0x23, 0xd3, 0xaf, - 0xdd, 0x94, 0x44, 0x8d, 0x14, 0x55, 0xfa, 0x65, 0xc3, 0x66, 0x73, 0xd9, - 0xc2, 0x6b, 0xfd, 0x36, 0x76, 0x51, 0x12, 0x34, 0x5d, 0x17, 0xff, 0x4d, - 0x0d, 0x9b, 0x3b, 0x28, 0x89, 0x1a, 0x24, 0xbb, 0xf7, 0x65, 0x11, 0x23, - 0x45, 0xe5, 0x74, 0x4e, 0x3a, 0xd3, 0x61, 0xe5, 0x4f, 0x19, 0xd3, 0xbe, - 0x06, 0xd6, 0xc5, 0x0d, 0x3f, 0xc3, 0xf9, 0x2b, 0xb2, 0x7e, 0xb3, 0xfe, - 0x4a, 0x4a, 0x1b, 0x72, 0x8f, 0xa9, 0x51, 0x5f, 0x3f, 0x09, 0xfc, 0xe8, - 0x4d, 0xdf, 0xfe, 0x99, 0x70, 0xd9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x59, - 0xb8, 0x3c, 0x3a, 0xff, 0x20, 0x39, 0x88, 0x2a, 0x1d, 0x7d, 0xc7, 0x57, - 0x59, 0xd7, 0x83, 0x28, 0x3a, 0x9a, 0x7e, 0x0a, 0xe6, 0x3e, 0x49, 0x2f, - 0xe0, 0x7c, 0x30, 0xdd, 0x1d, 0x7f, 0xee, 0x3f, 0x11, 0x4f, 0xea, 0x3d, - 0x3a, 0xfa, 0x51, 0x12, 0x34, 0x46, 0x77, 0xf2, 0x3a, 0xf6, 0xc6, 0x0e, - 0xb8, 0x5a, 0x75, 0x96, 0x75, 0xf9, 0x3b, 0xc8, 0x9b, 0xa7, 0xa4, 0xb2, - 0xdf, 0x22, 0xb7, 0xf4, 0x35, 0x3b, 0x1d, 0x3a, 0xff, 0xed, 0x20, 0x75, - 0x82, 0x16, 0xe6, 0x8e, 0xbd, 0xa7, 0xdc, 0xea, 0x6a, 0x72, 0xbd, 0x3f, - 0x5b, 0xf8, 0xa7, 0x68, 0xaf, 0xe8, 0x57, 0xfc, 0xdd, 0x63, 0xf8, 0x7d, - 0x2c, 0xeb, 0xff, 0xbe, 0x9d, 0x8f, 0x7c, 0x6e, 0xd7, 0x59, 0xd7, 0xe1, - 0x76, 0xea, 0x0e, 0xa4, 0x3e, 0xc9, 0xc8, 0xf7, 0xff, 0xff, 0xd9, 0xff, - 0xa2, 0xfa, 0x99, 0xb8, 0x87, 0xef, 0xcf, 0x13, 0x93, 0xec, 0xb9, 0xd7, - 0xe5, 0x3f, 0xf7, 0x59, 0xd7, 0x79, 0x69, 0xd4, 0x87, 0x81, 0x05, 0x17, - 0xff, 0xc1, 0xfe, 0xb7, 0x6b, 0x8f, 0xba, 0xf0, 0x11, 0x3a, 0xf3, 0xfd, - 0xce, 0xb2, 0x00, 0xfb, 0x67, 0x29, 0xdd, 0xc6, 0x4e, 0xbf, 0xdb, 0xe8, - 0x73, 0xa0, 0x73, 0xa9, 0x0f, 0x26, 0x05, 0xef, 0xbf, 0xc0, 0xcf, 0x1d, - 0x7f, 0xdf, 0x46, 0x34, 0xfc, 0x85, 0x73, 0xad, 0x88, 0x7c, 0x0b, 0x25, - 0xbd, 0xe7, 0x27, 0xf3, 0xaf, 0xf9, 0xd3, 0x88, 0xe2, 0xc8, 0x4e, 0xac, - 0x3d, 0x8e, 0x11, 0x5c, 0x8c, 0x1d, 0x72, 0xac, 0x3a, 0xb4, 0x6b, 0x7e, - 0x2d, 0x7f, 0xb3, 0x4f, 0xfd, 0x71, 0x0e, 0xbe, 0xf5, 0x37, 0x69, 0xd7, - 0xf9, 0xc7, 0xe9, 0xb0, 0xb9, 0xd5, 0xe9, 0xe9, 0x89, 0x1d, 0xa6, 0x9f, - 0x17, 0xdb, 0x5e, 0x10, 0xdb, 0x1a, 0x64, 0x78, 0x5b, 0xab, 0xb3, 0x0a, - 0x5e, 0x91, 0xf2, 0x18, 0x11, 0x08, 0xdf, 0x5c, 0x86, 0x10, 0x1a, 0x7e, - 0x9c, 0x9d, 0x3c, 0x43, 0xe6, 0x10, 0x97, 0xff, 0xa6, 0x5c, 0x36, 0x6c, - 0xec, 0xa2, 0x24, 0x68, 0x9a, 0x6f, 0xff, 0x4c, 0xb8, 0x6c, 0xd9, 0xd9, - 0x44, 0x48, 0xd1, 0x38, 0xdf, 0xfe, 0x99, 0x70, 0xd9, 0xb3, 0xb2, 0x88, - 0x91, 0xa2, 0x81, 0xbf, 0x76, 0x51, 0x12, 0x34, 0x5c, 0x17, 0xf0, 0xe7, - 0xe4, 0x9a, 0x3a, 0xe7, 0x43, 0xaf, 0xf0, 0xb5, 0xd0, 0x18, 0xb3, 0xab, - 0x11, 0x44, 0xb3, 0x3e, 0x15, 0x84, 0x52, 0xfc, 0xd9, 0x94, 0x9f, 0x54, - 0x3a, 0xa6, 0x3e, 0xc7, 0x3c, 0xbf, 0xb1, 0x96, 0xb8, 0xb4, 0xeb, 0xe7, - 0xf7, 0x18, 0x3a, 0xe4, 0x98, 0x4f, 0x3b, 0xc9, 0x65, 0xff, 0x36, 0x6c, - 0xec, 0xa2, 0x24, 0x68, 0x92, 0x6d, 0x37, 0x0f, 0xd2, 0x0b, 0xee, 0x63, - 0xd3, 0xaf, 0xf4, 0x7c, 0x73, 0x68, 0x13, 0xaf, 0xec, 0x18, 0xdd, 0xba, - 0x3a, 0xfe, 0x75, 0xf7, 0x01, 0xf3, 0xae, 0x89, 0x80, 0x8a, 0x05, 0x06, - 0x3a, 0x61, 0xa2, 0xca, 0xd9, 0x99, 0xa6, 0xd9, 0xfc, 0x49, 0x46, 0x0c, - 0xca, 0xbf, 0xaa, 0xfa, 0x8d, 0x97, 0xf0, 0xe4, 0x9d, 0x0c, 0x8b, 0xff, - 0x29, 0x13, 0x67, 0x65, 0x11, 0x23, 0x45, 0xa9, 0x7f, 0xe8, 0x6c, 0xd9, - 0xd9, 0x44, 0x48, 0xd1, 0x2a, 0xdc, 0x8c, 0x1d, 0x47, 0x5a, 0x65, 0x11, - 0x6a, 0xb4, 0xbf, 0xa5, 0x2a, 0x16, 0xbf, 0xd3, 0x67, 0x65, 0x11, 0x23, - 0x44, 0x53, 0x7f, 0xa6, 0xce, 0xca, 0x22, 0x46, 0x88, 0xd2, 0xe0, 0xf0, - 0xeb, 0xff, 0x03, 0x16, 0x9d, 0xcd, 0x32, 0xe7, 0x5f, 0xff, 0xf4, 0x07, - 0x5c, 0xc0, 0x79, 0xf3, 0xa4, 0xf3, 0xf4, 0xd3, 0x3e, 0x4e, 0xa4, 0x45, - 0x62, 0xb9, 0xed, 0xf4, 0xa2, 0x24, 0x68, 0xa7, 0xee, 0xfb, 0x9d, 0x5d, - 0x3c, 0x2f, 0x96, 0xdf, 0xfb, 0xec, 0xbf, 0xf9, 0x0c, 0xf8, 0xc3, 0xaf, - 0xff, 0x22, 0xc4, 0x3c, 0x4e, 0xe6, 0x99, 0x73, 0xaf, 0xfe, 0x0f, 0xfa, - 0x16, 0x75, 0x28, 0x67, 0x47, 0x5f, 0xfd, 0x8c, 0x84, 0x76, 0xd4, 0xa1, - 0x9d, 0x1d, 0x69, 0xa7, 0xc5, 0x4c, 0x2f, 0x0c, 0x2c, 0x67, 0x42, 0x28, - 0x41, 0x14, 0x8f, 0xa3, 0xdf, 0xfe, 0x99, 0x70, 0xd9, 0xb3, 0xb2, 0x88, - 0x91, 0xa2, 0x6a, 0xbf, 0xd3, 0x67, 0x65, 0x11, 0x23, 0x45, 0x77, 0x7d, - 0x28, 0x89, 0x1a, 0x2b, 0xeb, 0xcc, 0x30, 0xc1, 0x56, 0x12, 0xa6, 0x2f, - 0xeb, 0xa7, 0xd6, 0xb4, 0xcb, 0xcd, 0x7d, 0xce, 0xbc, 0xce, 0x70, 0xeb, - 0xff, 0x67, 0x18, 0x8f, 0xe9, 0xf3, 0x63, 0xad, 0xf3, 0xaf, 0xf9, 0x3b, - 0x9b, 0x23, 0x70, 0x07, 0x57, 0x4f, 0x1e, 0x04, 0x2f, 0xdb, 0xaa, 0xe0, - 0x7c, 0x9d, 0x6e, 0x9d, 0x47, 0x5b, 0x88, 0x5d, 0x74, 0x42, 0xd3, 0x62, - 0x6d, 0x8c, 0x91, 0x40, 0xe0, 0x8e, 0x6a, 0x10, 0xa1, 0x21, 0x9e, 0x47, - 0xbf, 0xfd, 0x32, 0xe1, 0xb3, 0x67, 0x65, 0x11, 0x23, 0x44, 0xf7, 0x7e, - 0xe3, 0xaa, 0x8d, 0xce, 0xbf, 0x76, 0x51, 0x12, 0x34, 0x5c, 0x36, 0x99, - 0xcf, 0x73, 0x0a, 0x6f, 0xfe, 0x9a, 0x1b, 0x36, 0x76, 0x51, 0x12, 0x34, - 0x49, 0xf4, 0xeb, 0xf4, 0x5b, 0x23, 0xb4, 0xfd, 0x49, 0x54, 0x12, 0x72, - 0x65, 0x5f, 0xb2, 0x85, 0xb8, 0xe5, 0xa8, 0x59, 0xce, 0x27, 0xbf, 0xd3, - 0x67, 0x65, 0x11, 0x23, 0x44, 0x55, 0x7e, 0xec, 0xa2, 0x24, 0x68, 0xa6, - 0x6f, 0xe4, 0xe6, 0x46, 0xfe, 0x9d, 0x69, 0xb0, 0xf8, 0x27, 0x8c, 0xef, - 0xff, 0x4c, 0xb8, 0x6c, 0xd9, 0xd9, 0x44, 0x48, 0xd1, 0x33, 0xdf, 0xfe, - 0x99, 0x70, 0xd9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x8d, 0xad, 0x93, 0x78, - 0x04, 0x27, 0xd4, 0x2b, 0xfa, 0xbd, 0xff, 0xa1, 0xb3, 0x67, 0x65, 0x11, - 0x23, 0x44, 0x75, 0x7f, 0xf7, 0x76, 0x9b, 0x43, 0x9f, 0xd3, 0xac, 0xea, - 0x99, 0x11, 0xee, 0x95, 0x70, 0x78, 0x75, 0xf4, 0xa4, 0x19, 0x1d, 0x7e, - 0xc1, 0x06, 0x6c, 0x75, 0xfe, 0x77, 0x96, 0x77, 0xb8, 0x75, 0x21, 0xeb, - 0x09, 0x35, 0xff, 0x87, 0x14, 0x86, 0x75, 0xc7, 0x01, 0xd7, 0xd2, 0x88, - 0x91, 0xa2, 0x9a, 0xbf, 0x66, 0xec, 0x47, 0x0e, 0xa4, 0x44, 0x9f, 0x4f, - 0x84, 0xb6, 0xff, 0xff, 0xb0, 0x7f, 0xa4, 0x96, 0x0e, 0xa5, 0xc4, 0xe4, - 0xbc, 0xec, 0x75, 0xff, 0x6a, 0x37, 0xc6, 0x5f, 0x9a, 0x3a, 0xee, 0x20, - 0xa2, 0x83, 0xec, 0xf7, 0xff, 0x37, 0x88, 0x3b, 0x68, 0x2f, 0xd6, 0x4e, - 0xbf, 0xed, 0x6a, 0x49, 0xde, 0xa6, 0xc7, 0x5d, 0xb3, 0x27, 0x5c, 0xea, - 0x1d, 0x7f, 0x23, 0xaf, 0x6c, 0x60, 0xeb, 0xff, 0xec, 0xff, 0x31, 0xbd, - 0x81, 0xff, 0x21, 0xa7, 0x5c, 0xfe, 0x9d, 0x7f, 0xa3, 0x77, 0x92, 0x4a, - 0x6e, 0xa2, 0x40, 0x4b, 0x7c, 0xa6, 0xd2, 0x26, 0x31, 0xc1, 0x8d, 0x42, - 0x9a, 0xfd, 0xfe, 0x31, 0x1b, 0x1d, 0x69, 0xa7, 0xc5, 0xc3, 0x07, 0x16, - 0x03, 0xc6, 0x42, 0xce, 0x50, 0xce, 0xdc, 0xb7, 0xa8, 0xbf, 0x8d, 0x47, - 0xc9, 0xad, 0xfb, 0xb2, 0x88, 0x91, 0xa2, 0xaa, 0xbf, 0xf4, 0x36, 0x6c, - 0xec, 0xa2, 0x24, 0x68, 0x9b, 0x6d, 0x36, 0x1f, 0xea, 0xcc, 0xef, 0xf4, - 0xd9, 0xd9, 0x44, 0x48, 0xd1, 0x5f, 0xdf, 0xbb, 0x28, 0x89, 0x1a, 0x2c, - 0x6b, 0x95, 0x34, 0xeb, 0x4d, 0x87, 0x96, 0xc9, 0x9d, 0xfb, 0x52, 0xe3, - 0xa8, 0x75, 0xff, 0x67, 0xff, 0x9d, 0x06, 0x09, 0xd7, 0x94, 0x6e, 0x1d, - 0x69, 0x84, 0xf4, 0xb4, 0x6d, 0x64, 0x99, 0x14, 0x5d, 0x7a, 0xbf, 0x76, - 0x51, 0x12, 0x34, 0x5a, 0xb7, 0xfe, 0x86, 0xcd, 0x9d, 0x94, 0x44, 0x8d, - 0x14, 0x15, 0xa6, 0xc3, 0xfd, 0x59, 0x9d, 0xfe, 0x71, 0xf5, 0xd5, 0xe1, - 0x67, 0x5d, 0xd7, 0x3a, 0x9a, 0x79, 0x2a, 0x8d, 0x2f, 0xa5, 0x11, 0x23, - 0x45, 0xc5, 0x7f, 0x06, 0x37, 0x06, 0x74, 0xea, 0xe9, 0xed, 0x68, 0xb6, - 0xf7, 0x5d, 0x67, 0x5f, 0x42, 0xa4, 0xd8, 0xeb, 0xf7, 0x02, 0xa6, 0x09, - 0xd7, 0x95, 0x24, 0x8e, 0xa0, 0x1e, 0x22, 0xa2, 0x7b, 0xfc, 0xeb, 0x89, - 0xcf, 0xd5, 0x47, 0x5f, 0xd9, 0xd8, 0xf8, 0x5c, 0xeb, 0xff, 0xe8, 0x17, - 0x45, 0x5a, 0x4d, 0x67, 0x32, 0x78, 0xeb, 0x32, 0x03, 0xfb, 0x9c, 0x57, - 0x69, 0x9d, 0x51, 0x0e, 0x3f, 0x74, 0x8b, 0x83, 0x70, 0xcf, 0xf2, 0x4f, - 0x30, 0xb0, 0xbf, 0x4f, 0xea, 0xdb, 0xd5, 0x1c, 0xeb, 0xf7, 0x65, 0x11, - 0x23, 0x45, 0xd3, 0x7e, 0x71, 0x80, 0x39, 0xd7, 0x9f, 0xea, 0x8e, 0xbe, - 0xc0, 0x60, 0x0e, 0xb4, 0xca, 0xc5, 0x19, 0x18, 0x68, 0x86, 0x7c, 0x24, - 0x81, 0xdb, 0xff, 0xec, 0x1f, 0xa2, 0xf8, 0xe8, 0x31, 0xd5, 0x0e, 0xbf, - 0xfc, 0xd7, 0xef, 0xbe, 0x35, 0xc7, 0x5c, 0x09, 0xd7, 0xf3, 0x61, 0xb0, - 0x32, 0x3a, 0xff, 0xf6, 0x7d, 0xd8, 0xf3, 0xb6, 0xb1, 0x6e, 0xae, 0x75, - 0xcb, 0x9b, 0x11, 0x8a, 0xca, 0x58, 0x95, 0xdf, 0x63, 0x0a, 0xd2, 0xce, - 0xbf, 0xe4, 0xe8, 0xbe, 0xeb, 0x8f, 0x9d, 0x7f, 0xff, 0xc1, 0xeb, 0x75, - 0xc8, 0x4e, 0xf7, 0xa1, 0xdd, 0x3b, 0x1a, 0x3a, 0xff, 0xc3, 0x0c, 0x7f, - 0x39, 0x0c, 0xc1, 0xd7, 0xff, 0xf7, 0x04, 0x30, 0xaf, 0x8d, 0xe6, 0x29, - 0x80, 0x64, 0x27, 0x5d, 0x2c, 0x3a, 0x9c, 0xfc, 0xd4, 0x5e, 0xbf, 0xf3, - 0x73, 0xbd, 0x86, 0xed, 0x8c, 0x1d, 0x7f, 0xf6, 0x01, 0xda, 0xfd, 0x7f, - 0x30, 0x27, 0x5f, 0xfa, 0x76, 0x35, 0x60, 0x49, 0xce, 0x03, 0xa9, 0x68, - 0x83, 0x84, 0x2b, 0xa2, 0x6d, 0x95, 0x0e, 0xb2, 0xcf, 0xd8, 0x58, 0x7c, - 0x8b, 0xcc, 0x30, 0xab, 0x8a, 0xae, 0x86, 0x52, 0xa5, 0xff, 0xbe, 0x92, - 0x40, 0x40, 0xa8, 0xe7, 0x5f, 0xf3, 0xef, 0xc8, 0xd7, 0xdd, 0x83, 0xa9, - 0xcf, 0xd7, 0xa7, 0x97, 0x07, 0x87, 0x5f, 0x87, 0x39, 0x1f, 0x3a, 0xfe, - 0x6c, 0x64, 0xe7, 0x01, 0xd5, 0x3e, 0x9e, 0x92, 0xb7, 0x92, 0xdf, 0x20, - 0x5a, 0xe7, 0x5f, 0xa1, 0x96, 0xa7, 0xce, 0xa6, 0x9e, 0x3f, 0xa4, 0x17, - 0xff, 0xfc, 0xe0, 0xe6, 0x6f, 0xf1, 0x8e, 0x7b, 0x1a, 0xd4, 0x76, 0x47, - 0x5f, 0xec, 0xcc, 0x51, 0x48, 0x69, 0xd4, 0xa2, 0x26, 0x3e, 0xcd, 0x7e, - 0x9c, 0x9d, 0xc0, 0x1d, 0x7f, 0xfd, 0xae, 0x26, 0xbf, 0xcc, 0x02, 0x6b, - 0x04, 0xeb, 0xdc, 0x71, 0xc3, 0xf5, 0x09, 0x45, 0xfe, 0x75, 0xe2, 0x2d, - 0xd5, 0xce, 0xbf, 0xcd, 0x5e, 0x90, 0x77, 0x69, 0xd5, 0x23, 0xe6, 0x64, - 0xce, 0xf4, 0x44, 0x8d, 0x12, 0x65, 0xe5, 0x49, 0xa3, 0xaa, 0x47, 0x88, - 0xa8, 0x9e, 0xfd, 0x25, 0x63, 0x3f, 0xab, 0x53, 0xe9, 0xd7, 0xfb, 0x37, - 0xff, 0xe1, 0xba, 0x3a, 0x9c, 0xfc, 0x3a, 0x7b, 0x7f, 0xff, 0x93, 0xb9, - 0xea, 0x7a, 0xc6, 0x24, 0xe1, 0xcf, 0xf1, 0x0e, 0xa6, 0xaa, 0x14, 0xc8, - 0x4b, 0xf5, 0x9d, 0x70, 0x94, 0xe1, 0x0d, 0xfc, 0x0f, 0x67, 0xdd, 0x7b, - 0x3c, 0x75, 0xed, 0x20, 0x0e, 0xbf, 0x85, 0xf7, 0x5c, 0x7c, 0xeb, 0xfe, - 0x79, 0x7c, 0x3c, 0xeb, 0xb0, 0x75, 0xff, 0x6f, 0x24, 0xee, 0x99, 0x78, - 0x3a, 0xee, 0x23, 0x28, 0xb9, 0xe8, 0xda, 0xcb, 0x3e, 0x73, 0x7d, 0xf4, - 0x5c, 0x1d, 0x7f, 0x93, 0x9a, 0x7f, 0xb8, 0x0e, 0xac, 0x3d, 0x1f, 0x90, - 0x5f, 0xf3, 0xf3, 0xe9, 0xb2, 0xde, 0x47, 0x5f, 0xff, 0xa2, 0x5d, 0x7e, - 0x0e, 0x7f, 0x26, 0x61, 0x86, 0x0a, 0xa6, 0xa2, 0xc3, 0x44, 0x3f, 0x38, - 0xbf, 0xa5, 0x20, 0xc8, 0x5c, 0xeb, 0xff, 0x47, 0xdf, 0xba, 0xe3, 0x8f, - 0xce, 0xbf, 0x63, 0x52, 0x27, 0x1d, 0x60, 0x89, 0xf1, 0xe8, 0xf2, 0xff, - 0xfe, 0x9c, 0x9c, 0x17, 0x6f, 0x7a, 0x1d, 0xd3, 0xb1, 0xa3, 0xaf, 0x95, - 0x3f, 0x34, 0x75, 0x39, 0xff, 0xe2, 0xe5, 0xfa, 0x1b, 0xe7, 0x19, 0x3a, - 0xff, 0xf3, 0xec, 0x39, 0x9b, 0x7d, 0x47, 0x16, 0x9d, 0x7f, 0xe8, 0x1d, - 0xb9, 0x0b, 0x4d, 0x21, 0xd4, 0x28, 0x85, 0x61, 0x26, 0xf3, 0x0c, 0x30, - 0x55, 0xf6, 0xcb, 0x4d, 0x15, 0x31, 0x7f, 0x73, 0x80, 0xeb, 0x76, 0x0f, - 0x1c, 0x4c, 0xaf, 0xf3, 0x5f, 0xbb, 0x3f, 0x76, 0x3a, 0xfe, 0xd6, 0x93, - 0x07, 0xd3, 0xaf, 0x77, 0x15, 0xce, 0xbf, 0xf3, 0xb1, 0xe7, 0x6d, 0x62, - 0xdd, 0x5c, 0xea, 0xea, 0x23, 0x96, 0x59, 0xf1, 0xea, 0x74, 0x79, 0x64, - 0x30, 0xaf, 0xc9, 0xfd, 0xb1, 0x83, 0xaf, 0xf9, 0xe5, 0xc1, 0x0f, 0xdf, - 0x47, 0x5f, 0xff, 0xbf, 0xcc, 0x6f, 0x89, 0x71, 0x3f, 0xbc, 0x93, 0xa7, - 0x57, 0x51, 0x6e, 0xb2, 0x81, 0x37, 0xbf, 0xe5, 0xbf, 0x67, 0x67, 0x5d, - 0x93, 0xaf, 0xfd, 0xd9, 0x2d, 0xf7, 0xd6, 0x4e, 0xc3, 0xaf, 0xe1, 0xf1, - 0x3d, 0x9d, 0x73, 0xa9, 0xcf, 0xc2, 0x10, 0x2f, 0xfb, 0x23, 0xdf, 0x18, - 0x08, 0x69, 0xd7, 0xfd, 0xe0, 0x7c, 0x6b, 0x68, 0x8e, 0x1d, 0x7f, 0xfa, - 0x36, 0xe2, 0x38, 0xe3, 0x29, 0xd4, 0x3a, 0xb1, 0x3b, 0x5f, 0x4b, 0xf5, - 0x0a, 0xaf, 0x90, 0x04, 0xe5, 0x83, 0xcb, 0xf0, 0xe7, 0x23, 0xe7, 0x5f, - 0xf9, 0xae, 0x3b, 0x79, 0xe8, 0x85, 0xa7, 0x52, 0xb9, 0xf2, 0xb2, 0x4b, - 0x7d, 0xfd, 0xb0, 0x07, 0x5f, 0xf2, 0x29, 0xe7, 0xbe, 0xad, 0x34, 0x75, - 0x32, 0x7b, 0xd3, 0xc4, 0x57, 0x98, 0x61, 0x83, 0xaf, 0xff, 0xd8, 0xbf, - 0x8b, 0xfb, 0x80, 0xd6, 0x2d, 0xe4, 0x54, 0xc5, 0xfd, 0xfe, 0xeb, 0xfd, - 0x24, 0x80, 0x3a, 0xdd, 0x3a, 0x95, 0x93, 0xc1, 0xf2, 0x63, 0x58, 0x9c, - 0xb2, 0x42, 0x13, 0x88, 0xba, 0x85, 0x25, 0xef, 0xb7, 0x87, 0x59, 0x0e, - 0xbf, 0xb8, 0xfe, 0x24, 0x9b, 0x1d, 0x7f, 0x76, 0x3a, 0x2e, 0xd3, 0xaf, - 0xff, 0xa3, 0xfc, 0xc9, 0xdc, 0x4f, 0x1a, 0xd2, 0x2c, 0xeb, 0xff, 0x23, - 0x53, 0xbb, 0xb8, 0xbe, 0x8e, 0xa5, 0x6c, 0x8f, 0x70, 0x07, 0xf4, 0xbc, - 0x4a, 0xfe, 0xa5, 0x73, 0x66, 0x9f, 0x1b, 0x13, 0xc9, 0xfd, 0xa1, 0xdd, - 0x5b, 0x0b, 0xbc, 0x95, 0x5a, 0xa2, 0xac, 0xa1, 0xe3, 0xbc, 0x69, 0x48, - 0x60, 0xcc, 0x23, 0xfb, 0x0a, 0x65, 0x90, 0x72, 0x15, 0xd1, 0x08, 0x91, - 0x8c, 0x63, 0x52, 0xa4, 0xbf, 0x29, 0x66, 0x79, 0x1b, 0xcc, 0x62, 0x77, - 0xff, 0xbb, 0x8c, 0x03, 0x98, 0xc8, 0xe7, 0x5a, 0x75, 0xee, 0xe2, 0xb9, - 0xd7, 0xfe, 0x76, 0x3c, 0xed, 0xac, 0x5b, 0xab, 0x9d, 0x5d, 0x45, 0x62, - 0xd2, 0xbe, 0x3d, 0x7f, 0xfd, 0x0b, 0x7e, 0xcb, 0xa1, 0x53, 0xa1, 0x8d, - 0x1d, 0x58, 0x88, 0x00, 0x98, 0x5f, 0xee, 0xc8, 0x30, 0x05, 0xb9, 0xd7, - 0xff, 0x3f, 0x7c, 0xfd, 0x3f, 0xcc, 0x02, 0x1d, 0x7f, 0xee, 0x0b, 0xed, - 0xe7, 0x9c, 0x85, 0x73, 0xa9, 0xd1, 0x73, 0xb1, 0x96, 0x22, 0x5f, 0xd1, - 0x29, 0x98, 0x61, 0x83, 0xaf, 0xe7, 0xec, 0x35, 0x38, 0x75, 0xfb, 0x17, - 0xc8, 0x01, 0xd6, 0x99, 0xdb, 0xa4, 0x7c, 0x8c, 0x45, 0x43, 0xc9, 0x4a, - 0xe1, 0xec, 0x28, 0x22, 0xb1, 0x5d, 0x19, 0x52, 0x1a, 0x86, 0xdc, 0xe2, - 0xf6, 0x0c, 0x55, 0x15, 0xd3, 0x5d, 0x36, 0x28, 0x27, 0x14, 0xf7, 0x8c, - 0x6f, 0xa5, 0x0b, 0x84, 0x57, 0x21, 0x97, 0xec, 0x29, 0xb5, 0x2a, 0x4b, - 0xf1, 0x9c, 0x86, 0xba, 0x9b, 0xbf, 0xb4, 0xec, 0xb5, 0x19, 0x3a, 0xff, - 0xf3, 0xed, 0x9f, 0x71, 0x4f, 0x73, 0x7f, 0x9d, 0x69, 0xb4, 0x7e, 0xfe, - 0x4b, 0xaf, 0xdd, 0x94, 0x44, 0x8d, 0x11, 0xad, 0xe5, 0x37, 0xd1, 0xd6, - 0x9b, 0x0f, 0x47, 0xe6, 0x77, 0xee, 0xca, 0x22, 0x46, 0x8a, 0x96, 0xe8, - 0x91, 0xa2, 0x1a, 0xb4, 0xd8, 0x7a, 0xb0, 0x67, 0x7e, 0xec, 0xa2, 0x24, - 0x68, 0x8f, 0xaf, 0xff, 0x86, 0x3e, 0xd7, 0x53, 0xc3, 0xff, 0x4f, 0xe9, - 0xd7, 0xa1, 0xb3, 0x62, 0x21, 0x3c, 0x99, 0xdf, 0xfe, 0x5e, 0x4d, 0xe5, - 0xfb, 0x83, 0xfc, 0xe1, 0xd5, 0x32, 0x20, 0x1c, 0xda, 0xff, 0xff, 0x9a, - 0x1e, 0xa9, 0x1a, 0xc0, 0x3e, 0xfa, 0xf3, 0xf5, 0x11, 0x43, 0xaf, 0xe0, - 0xef, 0xbb, 0x73, 0xe7, 0x5f, 0xbb, 0x28, 0x89, 0x1a, 0x2c, 0x7b, 0xa3, - 0x47, 0x5f, 0xdb, 0x79, 0xef, 0x73, 0xa7, 0x53, 0x4f, 0x16, 0x05, 0x6f, - 0xf8, 0x61, 0x4e, 0x23, 0x8e, 0xc7, 0x5f, 0xd8, 0x9f, 0xfa, 0x7c, 0xeb, - 0xf6, 0x77, 0x31, 0x93, 0xad, 0x33, 0xa7, 0x79, 0xb3, 0x66, 0x17, 0xa3, - 0xc3, 0x24, 0x3a, 0x37, 0xf2, 0x57, 0x79, 0x58, 0xad, 0x43, 0xaf, 0xe9, - 0xf4, 0x73, 0x91, 0xf3, 0xaf, 0xf8, 0x63, 0xdd, 0x47, 0xff, 0x07, 0x5f, - 0xfb, 0x18, 0xee, 0x0c, 0x6e, 0xdd, 0x1d, 0x7e, 0xcd, 0x71, 0x18, 0x3a, - 0xfb, 0xd5, 0xa7, 0x4e, 0xbf, 0xff, 0xe7, 0xe8, 0xe0, 0x33, 0x9c, 0x49, - 0x71, 0x3f, 0xa8, 0xdc, 0xea, 0x44, 0x43, 0x70, 0x8a, 0xfe, 0x7e, 0xfb, - 0x3c, 0x1f, 0x9d, 0x7f, 0xce, 0x3f, 0x9f, 0xe3, 0xe1, 0x73, 0xaf, 0xff, - 0x3f, 0x1d, 0x72, 0xe2, 0x7f, 0x31, 0x67, 0x5e, 0x88, 0x91, 0xa2, 0xd0, - 0xbf, 0xf4, 0x30, 0xaa, 0x51, 0xdd, 0xb1, 0x83, 0xaf, 0xef, 0x5c, 0x5f, - 0xfa, 0x3a, 0xa4, 0x89, 0x5e, 0x93, 0xfa, 0x85, 0x7f, 0xff, 0xfc, 0x9d, - 0xe4, 0x0a, 0x3f, 0xd3, 0x8f, 0xae, 0x66, 0xbb, 0x92, 0xcf, 0x9d, 0x4d, - 0x4f, 0xc4, 0x06, 0x32, 0x3b, 0xec, 0x37, 0x38, 0x63, 0x7f, 0xfa, 0x23, - 0x79, 0xdc, 0x57, 0x4f, 0x8b, 0xac, 0xeb, 0xff, 0xf2, 0x7f, 0x51, 0xbe, - 0xb5, 0x9c, 0x4d, 0x07, 0x63, 0xaf, 0xff, 0x83, 0xb7, 0x53, 0xfb, 0x07, - 0xad, 0xd2, 0xba, 0x1d, 0x5c, 0x45, 0x58, 0xab, 0x5f, 0xff, 0x07, 0xbd, - 0x71, 0xc5, 0x13, 0x9c, 0xcf, 0x27, 0x5a, 0x7e, 0x3a, 0xdd, 0xe9, 0xf2, - 0x85, 0x42, 0xfc, 0x32, 0x8d, 0x21, 0xd7, 0xff, 0xf7, 0x45, 0xdf, 0x7f, - 0x1a, 0xf8, 0xb8, 0x38, 0xff, 0x3a, 0xe4, 0xe1, 0xd7, 0xcd, 0x18, 0xf2, - 0x75, 0xff, 0x20, 0x23, 0xde, 0xf6, 0x3d, 0x3a, 0x9d, 0x1e, 0x18, 0x4a, - 0xae, 0xb7, 0x02, 0xa1, 0x22, 0xbd, 0x0a, 0xe8, 0x75, 0xff, 0xbc, 0xfd, - 0x44, 0x51, 0xf0, 0x5c, 0xeb, 0xf7, 0x9f, 0x8b, 0xfa, 0x75, 0x6e, 0x88, - 0x5e, 0x8e, 0xce, 0x3f, 0xbf, 0x3f, 0xf3, 0x8e, 0x75, 0xff, 0xff, 0xee, - 0x20, 0x31, 0x36, 0xe3, 0xbf, 0x8c, 0xdd, 0xba, 0x4f, 0xc0, 0xe1, 0xd7, - 0xfe, 0xcd, 0xdb, 0xa6, 0x7b, 0x1f, 0xd1, 0xd7, 0xff, 0xd9, 0xfd, 0x63, - 0x3c, 0x79, 0xd9, 0xce, 0x39, 0xd7, 0xfc, 0x2e, 0xec, 0xe4, 0xe4, 0xe9, - 0xd5, 0xb2, 0x6c, 0x72, 0x25, 0xf5, 0xd8, 0x50, 0x3e, 0xa1, 0x7e, 0xf0, - 0xcb, 0x51, 0x93, 0xa9, 0xd5, 0x06, 0xe4, 0x72, 0xc8, 0x99, 0x7f, 0xff, - 0xdf, 0xe3, 0x8e, 0x7b, 0xac, 0x07, 0x1f, 0x65, 0x84, 0x40, 0x75, 0xff, - 0xfc, 0xec, 0xe0, 0x38, 0xf3, 0xb9, 0x9f, 0x17, 0x75, 0x9d, 0x7f, 0x6f, - 0xaf, 0x3b, 0x04, 0x4e, 0xbf, 0xe7, 0x97, 0x11, 0x98, 0x8d, 0x8e, 0xa5, - 0xa3, 0x0e, 0x16, 0xbd, 0x31, 0xbf, 0xcd, 0x7e, 0xec, 0xfd, 0xd8, 0xeb, - 0xfe, 0x40, 0x8b, 0x7a, 0xf8, 0x03, 0xaf, 0xff, 0xfb, 0x98, 0xd9, 0x71, - 0x38, 0xf9, 0xd6, 0xfc, 0x5d, 0x7a, 0x3a, 0xb4, 0x89, 0xaf, 0x9b, 0x53, - 0xa3, 0xc7, 0x21, 0x9d, 0x7f, 0xbb, 0x26, 0x71, 0x38, 0x13, 0xaf, 0xf2, - 0xde, 0x43, 0x1b, 0xfc, 0xeb, 0xfb, 0xaf, 0xfd, 0xb1, 0x83, 0xaf, 0xff, - 0xff, 0x90, 0x3d, 0xe6, 0x32, 0xcc, 0x75, 0x9f, 0xf0, 0x3e, 0xeb, 0x12, - 0x70, 0x1c, 0xeb, 0xf7, 0xf9, 0x02, 0xa1, 0xd7, 0xfc, 0x21, 0xd8, 0x1c, - 0xc1, 0x73, 0xad, 0x80, 0x47, 0x06, 0x42, 0x0a, 0x44, 0xf7, 0xff, 0xbb, - 0xec, 0xbd, 0x1c, 0xfe, 0xa2, 0x04, 0xea, 0x74, 0xfd, 0x70, 0xcd, 0x0c, - 0x86, 0x30, 0xe0, 0x9c, 0xdf, 0xec, 0xe3, 0x29, 0xc4, 0x59, 0xd7, 0xf9, - 0xb9, 0xdd, 0x0b, 0xec, 0x75, 0xec, 0xe4, 0x1d, 0x7e, 0x64, 0x01, 0x08, - 0x9d, 0x40, 0x3c, 0x28, 0x1a, 0xbf, 0xd8, 0xc6, 0x4a, 0x58, 0xc1, 0xd7, - 0x94, 0x68, 0x4e, 0xbf, 0x71, 0xfb, 0xb2, 0xce, 0xbf, 0xc1, 0x81, 0xe6, - 0x43, 0x27, 0x5b, 0x76, 0x4f, 0x65, 0x82, 0x8a, 0x44, 0x50, 0xc3, 0xb5, - 0x62, 0x3d, 0x46, 0x1a, 0x95, 0x89, 0xf1, 0x6e, 0x65, 0x0e, 0x9a, 0x8c, - 0x5a, 0xef, 0xb9, 0xd7, 0x47, 0xce, 0xb6, 0x74, 0xd5, 0x70, 0x56, 0xfe, - 0x41, 0x0b, 0x73, 0x47, 0x5f, 0xfb, 0x3e, 0xfb, 0xfb, 0x1c, 0xe2, 0x1d, - 0x65, 0x9d, 0x7f, 0x20, 0x85, 0xb9, 0xaf, 0x07, 0x9d, 0x38, 0xfa, 0x94, - 0x46, 0x07, 0xde, 0x6d, 0x34, 0xf8, 0xd8, 0xc5, 0xcf, 0xe4, 0x6e, 0x61, - 0xb1, 0xbb, 0x4f, 0x81, 0x0a, 0xdc, 0x94, 0x26, 0xa2, 0x84, 0xa1, 0xf0, - 0x90, 0x87, 0x5c, 0x63, 0x1c, 0x95, 0xb9, 0x06, 0xbe, 0xc6, 0x52, 0x31, - 0x90, 0xea, 0x50, 0xdf, 0xe5, 0x17, 0xcf, 0x36, 0xf9, 0x87, 0x35, 0xfc, - 0xa9, 0x00, 0x2e, 0xc9, 0xd7, 0x9e, 0x04, 0xeb, 0xec, 0xe4, 0x7c, 0xeb, - 0x4f, 0xb8, 0x7c, 0xfc, 0x2e, 0x11, 0x9b, 0xcb, 0xd2, 0x87, 0x5f, 0x66, - 0xbd, 0x43, 0xaf, 0xdd, 0x94, 0x44, 0x8d, 0x16, 0xb5, 0xfd, 0x8a, 0xb5, - 0x03, 0x23, 0xaf, 0x75, 0xd6, 0x75, 0xfd, 0xcc, 0xd3, 0xec, 0xa8, 0xeb, - 0xfe, 0x6c, 0xd9, 0xd9, 0x44, 0x48, 0xd1, 0x41, 0xd6, 0x1f, 0xa4, 0x17, - 0xdf, 0x63, 0x2f, 0xf3, 0xaf, 0xf9, 0xda, 0xfd, 0xd9, 0xfb, 0xb1, 0xd7, - 0xff, 0xef, 0xe9, 0x36, 0x8d, 0x40, 0xc7, 0xf8, 0xec, 0x9d, 0x69, 0xa7, - 0xf5, 0x46, 0x6e, 0x70, 0xd1, 0xdc, 0x21, 0x64, 0xcf, 0xa5, 0xab, 0x84, - 0x7f, 0x08, 0x04, 0x87, 0xc9, 0xcd, 0xff, 0xe9, 0x97, 0x0d, 0x9b, 0x3b, - 0x28, 0x89, 0x1a, 0x28, 0xbb, 0xfd, 0x36, 0x76, 0x51, 0x12, 0x34, 0x5d, - 0x54, 0xed, 0xd9, 0x23, 0x5f, 0x24, 0xfa, 0x91, 0x95, 0xae, 0x3d, 0xfe, - 0x56, 0x3f, 0x1e, 0xcb, 0xf5, 0xd4, 0x27, 0xbe, 0xaf, 0x7e, 0xec, 0xa2, - 0x24, 0x68, 0x88, 0x6f, 0x73, 0x00, 0x75, 0xf6, 0x4e, 0x4e, 0x9d, 0x69, - 0xb0, 0xfc, 0x37, 0x33, 0x57, 0x1b, 0xbe, 0x7e, 0x3a, 0xce, 0xbe, 0x94, - 0x44, 0x8d, 0x11, 0xb5, 0xd3, 0x64, 0x8f, 0x37, 0xa4, 0x17, 0xfa, 0x6c, - 0xec, 0xa2, 0x24, 0x68, 0xa6, 0xef, 0xdd, 0x94, 0x44, 0x8d, 0x15, 0x05, - 0xec, 0xdd, 0x83, 0xad, 0x36, 0x1e, 0x87, 0x0c, 0xef, 0xf4, 0xd9, 0xd9, - 0x44, 0x48, 0xd1, 0x53, 0x5f, 0xbb, 0x28, 0x89, 0x1a, 0x2b, 0x0b, 0xf2, - 0x30, 0x00, 0xf4, 0xeb, 0xfe, 0x6c, 0xd9, 0xd9, 0x44, 0x48, 0xd1, 0x1f, - 0xde, 0xc7, 0xd8, 0xeb, 0xfd, 0x9b, 0xb6, 0x1a, 0x82, 0x75, 0xd1, 0xf3, - 0xad, 0x36, 0x26, 0x03, 0x23, 0x38, 0x28, 0x14, 0x5f, 0x8d, 0xcf, 0x18, - 0xdf, 0xfe, 0x99, 0x70, 0xd9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x6f, 0xbf, - 0xf9, 0x70, 0xd9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x7e, 0xb8, 0x64, 0x75, - 0xfe, 0x97, 0x13, 0xf9, 0x8b, 0x3a, 0xe9, 0xd2, 0x3c, 0x60, 0x54, 0xe7, - 0xd7, 0xa1, 0x5f, 0x98, 0xdf, 0xe5, 0x60, 0xac, 0x8e, 0x6c, 0xfb, 0x9d, - 0x7e, 0x56, 0xa7, 0xd9, 0xec, 0xdc, 0xeb, 0xf4, 0xf8, 0xa2, 0x98, 0xae, - 0x75, 0xd3, 0xa4, 0x78, 0xc0, 0x6d, 0xc3, 0xa9, 0x5a, 0x46, 0xca, 0xb2, - 0x7c, 0xac, 0x0d, 0x7e, 0x62, 0x12, 0x5b, 0xfe, 0x56, 0x1c, 0x8f, 0xfe, - 0x21, 0x83, 0xaf, 0xff, 0xf2, 0xb5, 0x3e, 0xeb, 0xae, 0x9f, 0xe6, 0x01, - 0x35, 0x83, 0xe9, 0xd7, 0xee, 0x24, 0x7a, 0xac, 0x0e, 0xa5, 0x65, 0x12, - 0xdf, 0x69, 0xbf, 0x4f, 0xea, 0xdb, 0xd5, 0x1c, 0xeb, 0xff, 0xe7, 0x77, - 0x77, 0x77, 0x77, 0x7d, 0xf4, 0x75, 0xfb, 0xa9, 0xb4, 0x2c, 0xab, 0x98, - 0x60, 0xaa, 0xc3, 0x7e, 0xc1, 0x3d, 0x82, 0x54, 0xc6, 0x86, 0x9d, 0x19, - 0x5a, 0x85, 0x4d, 0xfa, 0x20, 0x5d, 0x51, 0xd7, 0xff, 0x71, 0xd3, 0xa1, - 0x10, 0xfc, 0x3f, 0x3a, 0xf0, 0xa3, 0x9d, 0x7e, 0x7f, 0x2b, 0xe2, 0x1d, - 0x5d, 0x3c, 0x11, 0x19, 0xbf, 0x9b, 0xaf, 0xe0, 0xa8, 0x75, 0xe6, 0x21, - 0x83, 0xaf, 0xff, 0x7f, 0xb1, 0xb0, 0x38, 0xfa, 0xf8, 0x78, 0x75, 0xd8, - 0xbe, 0x1f, 0x46, 0x87, 0x6f, 0xd1, 0x2e, 0x27, 0x4e, 0xbf, 0xff, 0xfc, - 0x30, 0xa2, 0x75, 0xdb, 0xe3, 0x88, 0xb0, 0x3f, 0x89, 0xe0, 0xf1, 0x3a, - 0x75, 0xf4, 0x35, 0x37, 0x3a, 0xff, 0xdc, 0x4f, 0xe7, 0x7a, 0x1d, 0xa7, - 0x1d, 0x7f, 0xc9, 0xfc, 0xef, 0x43, 0xb4, 0xe3, 0xaf, 0x68, 0x23, 0xe0, - 0xff, 0x38, 0x83, 0x40, 0x4e, 0x8b, 0xa5, 0xbc, 0x26, 0x17, 0xdd, 0x42, - 0x76, 0xce, 0x75, 0xff, 0xf3, 0xee, 0xd8, 0x1f, 0x7c, 0x7a, 0x9d, 0x45, - 0x0e, 0xa9, 0xe3, 0xe2, 0x54, 0x1f, 0x7d, 0xb2, 0xd1, 0xa7, 0x5f, 0xb4, - 0x21, 0x86, 0x9d, 0x7f, 0xb8, 0xeb, 0x9b, 0xdf, 0x5c, 0xea, 0x73, 0xfd, - 0xc2, 0x24, 0x26, 0xbf, 0x99, 0x4e, 0x7f, 0x24, 0x75, 0x74, 0xf6, 0x60, - 0xb2, 0xff, 0xb7, 0x07, 0x97, 0x57, 0xe0, 0x74, 0x75, 0xff, 0xf8, 0x1c, - 0x7e, 0xa7, 0xaf, 0xe5, 0xd9, 0x17, 0x59, 0xd7, 0xf9, 0x47, 0x1f, 0xea, - 0x38, 0x75, 0x22, 0x22, 0x21, 0x5a, 0x9d, 0x1d, 0x03, 0x0c, 0x7b, 0xfe, - 0x7e, 0x3e, 0xdd, 0x7c, 0x01, 0xd7, 0xfd, 0xbe, 0xb9, 0x1e, 0x78, 0xed, - 0x3a, 0xf6, 0x63, 0x27, 0x59, 0x5c, 0xeb, 0xdf, 0x6e, 0x1d, 0x76, 0xb0, - 0xeb, 0xff, 0xb4, 0xfd, 0x97, 0xc7, 0x36, 0x81, 0x3a, 0x91, 0x10, 0xb0, - 0x27, 0xe8, 0xdf, 0xc5, 0x6f, 0xfe, 0x03, 0xfe, 0x35, 0x9c, 0xe2, 0x2c, - 0xeb, 0xdf, 0x46, 0x4e, 0xa7, 0x3d, 0xed, 0x21, 0x5f, 0x9d, 0x5d, 0x18, - 0x91, 0xd4, 0xeb, 0xff, 0xbb, 0x13, 0x80, 0x9b, 0x21, 0x09, 0xb9, 0x0a, - 0x4a, 0x37, 0x66, 0x16, 0x3d, 0x87, 0xea, 0xe3, 0x09, 0xe1, 0x34, 0x1b, - 0xfa, 0x76, 0x30, 0xa0, 0xfc, 0x26, 0xbc, 0x90, 0xdf, 0xff, 0xf2, 0xb7, - 0xcf, 0xef, 0x8a, 0xdd, 0xd9, 0xfd, 0x58, 0xce, 0x57, 0x56, 0x01, 0xf1, - 0xe3, 0x93, 0xc7, 0x5e, 0x67, 0xca, 0xce, 0xbf, 0xec, 0xfe, 0xb3, 0xfc, - 0xcf, 0x4e, 0xa8, 0x3d, 0x71, 0x1f, 0xba, 0x04, 0xea, 0xe9, 0xb4, 0x59, - 0x05, 0xf3, 0xff, 0x16, 0x75, 0xfb, 0xee, 0x29, 0xe9, 0xd5, 0xe0, 0xf1, - 0xb0, 0x82, 0xff, 0x77, 0x3b, 0xb3, 0xff, 0x47, 0x5e, 0x61, 0x86, 0x0e, - 0xbe, 0xd8, 0x51, 0xca, 0x98, 0xbf, 0xbb, 0x76, 0x9d, 0x7f, 0x94, 0x7f, - 0xeb, 0x90, 0x13, 0xaf, 0xc9, 0xb6, 0x6f, 0xf3, 0xae, 0x49, 0x1d, 0x6d, - 0xdd, 0x10, 0xea, 0x0b, 0xac, 0xcf, 0xe5, 0x14, 0xac, 0x55, 0x7d, 0x3c, - 0x64, 0x60, 0x67, 0x42, 0x3e, 0x29, 0x06, 0x16, 0xf7, 0xff, 0x4e, 0x63, - 0x34, 0x28, 0xfd, 0xcd, 0x8e, 0xbf, 0xf6, 0xa1, 0x4e, 0x23, 0x88, 0x5c, - 0xeb, 0xf4, 0x74, 0x31, 0xa3, 0xae, 0x6f, 0xce, 0xbe, 0x65, 0xff, 0x07, - 0x5f, 0xb6, 0x0f, 0xb8, 0x32, 0x36, 0xe1, 0x16, 0xbf, 0xf9, 0xf9, 0xe4, - 0x1f, 0x4c, 0x65, 0xd6, 0x75, 0xf3, 0xfc, 0x2b, 0x3a, 0xed, 0x48, 0xd1, - 0x07, 0x52, 0xcf, 0x13, 0xe4, 0x37, 0xff, 0xe5, 0xea, 0x1b, 0xc4, 0xcf, - 0xeb, 0xb8, 0x0c, 0x3a, 0xff, 0x9f, 0xe3, 0x93, 0x87, 0x34, 0x75, 0x3a, - 0x2b, 0x30, 0x8b, 0x4a, 0x77, 0xf4, 0x71, 0xd5, 0xc2, 0xd3, 0xaa, 0x4a, - 0x8b, 0xba, 0xba, 0xb3, 0xff, 0xc6, 0x6b, 0x38, 0xba, 0xff, 0x3b, 0x47, - 0x37, 0xfe, 0x1d, 0x7f, 0xa0, 0x7e, 0xdc, 0xee, 0x1d, 0x77, 0x40, 0x75, - 0xcc, 0x30, 0x75, 0x34, 0xd7, 0x30, 0x2d, 0x7d, 0xa7, 0x49, 0xc5, 0x4c, - 0x68, 0xae, 0xf7, 0x47, 0x5f, 0xc9, 0xc4, 0x51, 0x47, 0x3a, 0xed, 0x79, - 0x01, 0xe2, 0x7c, 0x5e, 0x91, 0x14, 0xfe, 0x5d, 0xef, 0x30, 0xc3, 0x05, - 0x51, 0x53, 0x17, 0xf7, 0xc8, 0xc2, 0x32, 0x55, 0x48, 0xde, 0x20, 0xd5, - 0xfb, 0x3a, 0xf3, 0xb0, 0xea, 0x75, 0xd2, 0x1c, 0x45, 0x49, 0x4d, 0x5d, - 0x54, 0x59, 0x8f, 0x23, 0x27, 0x17, 0xfd, 0x10, 0x5f, 0xe1, 0xdf, 0xfe, - 0x79, 0x1e, 0x9d, 0x78, 0x53, 0x47, 0x5f, 0x02, 0x07, 0xd3, 0xaf, 0xfe, - 0x71, 0xf4, 0x5f, 0x76, 0x5c, 0x7d, 0x3a, 0xb1, 0x16, 0xa8, 0x6d, 0xe8, - 0xd6, 0x88, 0x6c, 0x87, 0x5f, 0x6d, 0xb4, 0x6e, 0x75, 0xde, 0xe9, 0x0d, - 0x9f, 0x90, 0xfb, 0xf3, 0xe7, 0x78, 0x87, 0x5f, 0xfe, 0x63, 0xde, 0x66, - 0x6c, 0x99, 0x39, 0xf7, 0x3a, 0xff, 0xf7, 0xae, 0xbe, 0xf5, 0xf6, 0xfc, - 0x42, 0x87, 0x5e, 0xc5, 0xab, 0x9d, 0x7f, 0xb3, 0x43, 0x9f, 0xe2, 0x1d, - 0x40, 0x3c, 0xe1, 0x1e, 0xac, 0x4d, 0x6d, 0x92, 0xfe, 0x12, 0xfa, 0x9b, - 0x3a, 0x13, 0x37, 0xf7, 0xf1, 0x91, 0x75, 0x9e, 0x20, 0x2b, 0xf4, 0x08, - 0x38, 0xe6, 0x88, 0x0a, 0x63, 0x73, 0x7f, 0xf2, 0x6f, 0xa0, 0x60, 0xb8, - 0x85, 0xce, 0xbf, 0xf8, 0x32, 0x53, 0xb9, 0xbe, 0xbd, 0x8f, 0x9d, 0x7e, - 0x76, 0xc6, 0xec, 0x1d, 0x58, 0x8b, 0x04, 0x41, 0xea, 0x3d, 0xfe, 0xee, - 0xde, 0x31, 0x94, 0x59, 0xd7, 0xfe, 0x41, 0x53, 0xa2, 0x92, 0x08, 0x9d, - 0x4e, 0x7e, 0x58, 0x6d, 0x7c, 0xb7, 0xc5, 0x9d, 0x7f, 0xec, 0x5b, 0xc9, - 0x3f, 0xd0, 0xac, 0xeb, 0xc9, 0xbe, 0x8e, 0xb3, 0xb4, 0xf6, 0x7d, 0x3d, - 0xbf, 0xdd, 0x67, 0x48, 0x3f, 0x43, 0xaf, 0xb7, 0xf7, 0xae, 0x55, 0xcc, - 0x30, 0x55, 0x39, 0xbb, 0x60, 0x8e, 0xfe, 0x8e, 0xb5, 0xa2, 0x85, 0x4c, - 0x68, 0x69, 0xd7, 0x5d, 0x32, 0x3c, 0xa4, 0x84, 0x67, 0x61, 0xe7, 0xc8, - 0x50, 0x41, 0x00, 0xbc, 0xfc, 0xa0, 0x30, 0x8e, 0xbd, 0xb4, 0x2c, 0xeb, - 0xef, 0x86, 0x3c, 0x9a, 0x20, 0x7a, 0x83, 0xcc, 0x08, 0xe5, 0xe5, 0x74, - 0xf4, 0xeb, 0x9c, 0x27, 0x5f, 0x82, 0x3e, 0xf9, 0x69, 0xd7, 0xff, 0xc3, - 0x9a, 0xf1, 0xe7, 0x8f, 0xea, 0xe1, 0xbe, 0x30, 0xdf, 0xe8, 0x56, 0x82, - 0x8c, 0x99, 0xcb, 0xd7, 0xfe, 0xe0, 0x76, 0x7f, 0x0f, 0xf7, 0x01, 0xd7, - 0xa3, 0xbb, 0x1d, 0x73, 0x0c, 0x1d, 0x7f, 0xba, 0x99, 0x3b, 0xcb, 0x66, - 0x91, 0xb4, 0x60, 0x72, 0x80, 0x8c, 0x3e, 0xba, 0x5f, 0xfc, 0x38, 0xa7, - 0x21, 0xbe, 0x63, 0x77, 0x3a, 0x9c, 0xfa, 0x30, 0x8e, 0xff, 0xe5, 0xae, - 0x1b, 0x9d, 0x94, 0x44, 0x8d, 0x10, 0xc5, 0xff, 0xff, 0xe8, 0xd6, 0x0e, - 0x4b, 0x8f, 0xbb, 0x67, 0xb3, 0x92, 0x4c, 0x18, 0x50, 0xea, 0xc4, 0x63, - 0x05, 0x3e, 0x91, 0x52, 0xc7, 0x23, 0x50, 0x18, 0x73, 0x5f, 0xe5, 0xf2, - 0x36, 0x17, 0x69, 0xd7, 0xfc, 0xfb, 0xb7, 0x91, 0x02, 0xe7, 0x5f, 0xbb, - 0x28, 0x89, 0x1a, 0x20, 0xab, 0xdc, 0x75, 0x9d, 0x7f, 0xe7, 0xda, 0x3f, - 0xdc, 0x6c, 0xf6, 0x1d, 0x58, 0x88, 0xe4, 0x33, 0x11, 0xbb, 0xef, 0xe9, - 0xfd, 0x2a, 0xf4, 0x77, 0x62, 0xaf, 0x82, 0x30, 0xa1, 0x57, 0xf9, 0x36, - 0xcf, 0xe9, 0xfd, 0x2a, 0x8a, 0xbf, 0xb2, 0x4f, 0xc7, 0x59, 0x57, 0x30, - 0xc1, 0x57, 0xf0, 0xb8, 0xec, 0x9d, 0x2a, 0xb1, 0x30, 0xa9, 0x11, 0x2c, - 0x73, 0x84, 0x3e, 0x99, 0x88, 0x53, 0x05, 0x7e, 0x46, 0x2e, 0x4e, 0x95, - 0x31, 0xfa, 0x53, 0x53, 0xd2, 0xe4, 0x75, 0x74, 0xea, 0xbc, 0xb8, 0x65, - 0x12, 0xa5, 0xaf, 0xf7, 0x30, 0x74, 0x83, 0x87, 0x5f, 0xe8, 0x1c, 0xd7, - 0x5f, 0x47, 0x5f, 0xc0, 0xc1, 0x8f, 0xe8, 0xeb, 0x3b, 0x4f, 0x6f, 0x46, - 0x17, 0xee, 0xee, 0xdc, 0xf9, 0xd7, 0xff, 0xfd, 0xc4, 0xee, 0x02, 0x17, - 0x83, 0xf1, 0x76, 0x33, 0xfa, 0x3a, 0xce, 0x75, 0xfb, 0x8f, 0x38, 0x0f, - 0x23, 0xf2, 0xf5, 0x8e, 0xba, 0x8d, 0xbf, 0xc2, 0x6a, 0xff, 0x9f, 0x76, - 0xcf, 0x3c, 0xb1, 0x67, 0x5f, 0xff, 0xa4, 0xa4, 0x6b, 0x3a, 0xd4, 0xe4, - 0x0e, 0xed, 0x3a, 0xff, 0xd2, 0x7f, 0xeb, 0x3e, 0x9b, 0xb0, 0x75, 0xa3, - 0x11, 0x28, 0xa2, 0xad, 0x3a, 0x63, 0xfc, 0x28, 0x18, 0x67, 0xde, 0xfc, - 0x7a, 0x75, 0xff, 0xfa, 0x21, 0xb1, 0xcf, 0x19, 0xb0, 0x7e, 0x18, 0xf2, - 0x68, 0xbe, 0xef, 0xfd, 0xa4, 0x1d, 0xdb, 0xd0, 0xbe, 0x8e, 0xa6, 0x51, - 0x47, 0xf6, 0x5b, 0xfc, 0xfb, 0x73, 0x19, 0x75, 0x73, 0xad, 0x23, 0xaf, - 0xff, 0xf7, 0xa9, 0xd5, 0x38, 0xeb, 0x65, 0xa8, 0x3c, 0x7e, 0xb9, 0xd6, - 0xfe, 0x1f, 0x8e, 0x84, 0x2f, 0xbe, 0x38, 0xd3, 0xa9, 0xcf, 0x1d, 0x09, - 0xef, 0xfc, 0x28, 0xdf, 0xf3, 0x3a, 0x9a, 0x3a, 0xff, 0x71, 0xda, 0x39, - 0x9b, 0x1d, 0x7f, 0xbf, 0xef, 0x91, 0x6f, 0x30, 0xf1, 0x00, 0xde, 0x8e, - 0xb4, 0xf1, 0x00, 0xd6, 0x1f, 0x50, 0x50, 0xae, 0x86, 0x9e, 0x20, 0x1b, - 0xe8, 0x1d, 0xda, 0x78, 0x80, 0x6f, 0xf2, 0x4b, 0x99, 0xef, 0xae, 0x78, - 0x80, 0x6f, 0x20, 0x80, 0xf1, 0x00, 0xd0, 0x11, 0x6e, 0xb2, 0x2e, 0x17, - 0x4e, 0x40, 0xbd, 0xd7, 0xf9, 0xe2, 0x01, 0xa3, 0xc4, 0x03, 0x73, 0xac, - 0xf1, 0x00, 0xd0, 0x0d, 0xca, 0x0b, 0xdf, 0x22, 0xc0, 0xe7, 0x88, 0x06, - 0xf7, 0xe2, 0x47, 0x88, 0x06, 0xff, 0xc3, 0x0d, 0x9b, 0x89, 0x28, 0xe9, - 0xe2, 0x01, 0xbf, 0xfa, 0x3e, 0x1d, 0x90, 0x7f, 0xc8, 0x69, 0xe2, 0x01, - 0xba, 0x00, 0x78, 0x80, 0x6f, 0xf0, 0xc3, 0x1a, 0xd3, 0xfa, 0x78, 0x80, - 0x6f, 0xc8, 0xa4, 0x0f, 0xa7, 0x88, 0x06, 0xe4, 0xd1, 0xe2, 0x01, 0xae, - 0x9e, 0xb7, 0xcd, 0x2f, 0xff, 0x71, 0x3f, 0xfc, 0xd7, 0x8e, 0xa3, 0xac, - 0xf1, 0x00, 0xdf, 0xbe, 0x2f, 0xbb, 0x4d, 0x10, 0x0d, 0xde, 0xb9, 0xe2, - 0x01, 0x98, 0xda, 0x5f, 0x91, 0xd7, 0x00, 0x3c, 0x40, 0x37, 0xc1, 0x81, - 0x91, 0xe2, 0x01, 0xbc, 0xfd, 0x91, 0xe2, 0x01, 0xbf, 0xf6, 0x6f, 0xa0, - 0x3e, 0x0f, 0xba, 0x3c, 0x40, 0x37, 0xe0, 0xc3, 0x5a, 0xe7, 0x88, 0x06, - 0xfd, 0x12, 0xe3, 0xee, 0x78, 0x80, 0x6b, 0x11, 0x65, 0xc4, 0xb0, 0x99, - 0xdd, 0xdf, 0x4f, 0x10, 0x0d, 0x35, 0x59, 0x28, 0x08, 0xb2, 0x12, 0xd2, - 0x22, 0x48, 0x45, 0xf0, 0xd3, 0xd3, 0x2d, 0x16, 0xfe, 0x1b, 0x41, 0x2f, - 0xbf, 0x67, 0xf5, 0x1b, 0x9e, 0x20, 0x1b, 0xfc, 0x07, 0x93, 0x3d, 0x7f, - 0x9e, 0x20, 0x10, 0x1b, 0x4b, 0xdd, 0x76, 0x0f, 0x10, 0x0d, 0x48, 0xfe, - 0x7a, 0xa1, 0x7f, 0x83, 0x0d, 0x6b, 0xf9, 0x59, 0xe2, 0x01, 0xbe, 0x41, - 0x6e, 0x8f, 0x10, 0x0d, 0xfd, 0x0c, 0xb7, 0x37, 0x69, 0xe2, 0x01, 0xac, - 0x46, 0x5f, 0x08, 0xbd, 0x41, 0x09, 0x6d, 0xff, 0x71, 0xf5, 0x36, 0x83, - 0xdf, 0x4f, 0x10, 0x0d, 0x90, 0xf1, 0x00, 0xdd, 0x1b, 0x00, 0xf9, 0x38, - 0x91, 0x77, 0x7d, 0x3c, 0x40, 0x37, 0xe8, 0xfe, 0x93, 0x73, 0xc4, 0x03, - 0x7f, 0x20, 0x85, 0xb9, 0xa3, 0xc4, 0x03, 0x4e, 0x89, 0x01, 0x24, 0xf9, - 0xa5, 0x01, 0x92, 0x99, 0x90, 0xd8, 0x64, 0xff, 0xac, 0x3c, 0x20, 0x82, - 0xdf, 0x4a, 0x05, 0x2b, 0x52, 0xdd, 0x7f, 0x28, 0x4e, 0x7a, 0x14, 0x3e, - 0x61, 0x7d, 0x7a, 0x22, 0x46, 0x88, 0x06, 0x64, 0x65, 0x5f, 0x28, 0xad, - 0x80, 0xb3, 0xaf, 0xe4, 0x9c, 0x2e, 0x0e, 0x1d, 0x7f, 0xf3, 0x47, 0x25, - 0xc4, 0xf7, 0xd0, 0xb2, 0x75, 0xde, 0xb9, 0x56, 0x50, 0xab, 0xdc, 0x7d, - 0x8e, 0xb9, 0x86, 0x0a, 0xa4, 0x3d, 0xb5, 0x71, 0x66, 0x44, 0x58, 0x1c, - 0xbc, 0xb4, 0xd1, 0x53, 0x1e, 0x05, 0xe4, 0x0f, 0xce, 0xbf, 0xfd, 0xfd, - 0x62, 0x89, 0xdf, 0x3e, 0xfa, 0xfb, 0x9d, 0x5b, 0x33, 0x45, 0x5a, 0x40, - 0x03, 0xc9, 0x52, 0xac, 0x50, 0xeb, 0xa5, 0x30, 0x5b, 0xec, 0x38, 0x7e, - 0x5b, 0xe4, 0x6e, 0xff, 0xf0, 0xfe, 0x7b, 0x19, 0x6c, 0x77, 0x60, 0x39, - 0xd7, 0xf7, 0xfc, 0xce, 0x9c, 0xfa, 0x3a, 0xff, 0x66, 0xff, 0xfc, 0x37, - 0x47, 0x5e, 0x1d, 0xda, 0x78, 0xc0, 0x2b, 0x11, 0xb8, 0x89, 0xbd, 0x33, - 0x83, 0x3b, 0xf3, 0x2d, 0x7e, 0xec, 0x75, 0xf3, 0xa8, 0xeb, 0x3a, 0xba, - 0x79, 0x4b, 0x29, 0xbf, 0xf3, 0x75, 0xe0, 0x71, 0x6f, 0xd5, 0x0e, 0xbf, - 0x9a, 0xfd, 0xf7, 0xca, 0xce, 0xbf, 0xfa, 0x70, 0xe6, 0xbf, 0x82, 0xdc, - 0xd1, 0xd7, 0xcb, 0x70, 0xfc, 0xea, 0xc3, 0xe4, 0x84, 0x3b, 0xb9, 0x18, - 0x8b, 0x41, 0x84, 0xa5, 0xff, 0x3c, 0x9d, 0x68, 0xbf, 0x50, 0xea, 0xe9, - 0xf4, 0x2a, 0x31, 0xbf, 0xbc, 0xb1, 0xd4, 0xce, 0x15, 0x7f, 0xf7, 0xa2, - 0x99, 0xbf, 0xd9, 0x6c, 0x74, 0xeb, 0xe6, 0x79, 0x0c, 0x9d, 0x7e, 0xc6, - 0x5a, 0xfb, 0x9d, 0x7b, 0x88, 0xc9, 0xd7, 0x85, 0xda, 0x55, 0xff, 0x87, - 0xd4, 0x54, 0xa8, 0x2d, 0x75, 0x73, 0xab, 0x0f, 0x7e, 0x06, 0xab, 0x74, - 0xca, 0xfa, 0x8a, 0x24, 0x7f, 0x28, 0x54, 0xf7, 0x4e, 0xad, 0x27, 0x08, - 0x92, 0x35, 0xce, 0x12, 0x44, 0x6b, 0x57, 0xf6, 0xfa, 0xef, 0x5f, 0xe7, - 0x5f, 0xcd, 0xd2, 0x9d, 0x89, 0x1d, 0x78, 0x7f, 0xa3, 0xaf, 0xda, 0x08, - 0x86, 0x47, 0x53, 0x9f, 0x82, 0x17, 0x04, 0x6e, 0xff, 0xee, 0x30, 0xfd, - 0xd6, 0x31, 0x1d, 0x50, 0xeb, 0xa7, 0xed, 0x1d, 0x7e, 0x71, 0x4d, 0xda, - 0x75, 0xff, 0x71, 0xfa, 0xf2, 0x41, 0x91, 0xd7, 0xdf, 0x52, 0x35, 0xd3, - 0xdc, 0x54, 0x4d, 0x4d, 0x47, 0xc8, 0x51, 0x98, 0x77, 0xbf, 0xf7, 0x31, - 0x54, 0x0a, 0x99, 0xbf, 0xce, 0xbf, 0xec, 0x97, 0x10, 0x1c, 0x0a, 0x87, - 0x5e, 0xfe, 0x48, 0xea, 0x59, 0xea, 0x68, 0xe6, 0x94, 0x45, 0xb7, 0xb0, - 0x94, 0xbf, 0xe5, 0x23, 0xc3, 0xac, 0x51, 0x43, 0xaf, 0xfd, 0x1a, 0x5b, - 0xa7, 0x7a, 0x8c, 0x1d, 0x6d, 0x28, 0x7e, 0xfc, 0x3a, 0xbf, 0xec, 0xff, - 0xd1, 0x4f, 0xe4, 0x8e, 0xbf, 0xc0, 0x7d, 0xf5, 0x9b, 0xfc, 0xeb, 0xfe, - 0x7f, 0xa4, 0x90, 0x0f, 0xf3, 0xad, 0xa0, 0x22, 0x8b, 0x0e, 0x3a, 0x69, - 0x5b, 0xa6, 0x01, 0xf8, 0x65, 0xdf, 0xf7, 0xd3, 0x67, 0xdf, 0xde, 0xb9, - 0xd7, 0xb5, 0xfc, 0x3a, 0xec, 0xd7, 0x83, 0xd5, 0xf2, 0x75, 0x7f, 0x4f, - 0x67, 0xfd, 0x8f, 0x9d, 0x7f, 0xfe, 0x7e, 0x46, 0x0b, 0xf5, 0x40, 0x06, - 0x3a, 0xd3, 0xa9, 0xa8, 0xb4, 0xf9, 0x8a, 0xa3, 0x0a, 0x75, 0x7d, 0xa9, - 0x0e, 0x78, 0x8e, 0x84, 0x31, 0x99, 0xdf, 0x71, 0x21, 0xa7, 0x5f, 0xf7, - 0x70, 0x7c, 0x73, 0x37, 0x60, 0xeb, 0xfe, 0x68, 0x87, 0xdf, 0x12, 0x5f, - 0xa7, 0x56, 0xc8, 0x98, 0xc2, 0x0d, 0xce, 0xef, 0xf8, 0x5f, 0x37, 0xfe, - 0x75, 0xce, 0xa7, 0x3e, 0x78, 0x31, 0xbf, 0x44, 0xe0, 0x01, 0xce, 0xbb, - 0x5a, 0x3a, 0xf3, 0x0c, 0x30, 0x75, 0xde, 0xc1, 0x53, 0x17, 0xf5, 0xd3, - 0xdb, 0xd1, 0xad, 0xff, 0xb3, 0x43, 0x0a, 0x32, 0x28, 0xc9, 0xd7, 0xf7, - 0xae, 0xde, 0x79, 0xd1, 0xd7, 0xa3, 0xdc, 0x2a, 0x9a, 0x99, 0x72, 0xe1, - 0x07, 0xc2, 0x2f, 0x4f, 0xa7, 0x8c, 0x2f, 0xc0, 0xea, 0x07, 0x63, 0xaf, - 0xf3, 0x18, 0x39, 0x39, 0x3a, 0x75, 0xfc, 0x39, 0xbf, 0xbe, 0x5a, 0x75, - 0x32, 0x88, 0xb1, 0x28, 0xf9, 0x9d, 0xd0, 0xb3, 0xaf, 0xf6, 0x4e, 0xc9, - 0x98, 0x61, 0x82, 0xaf, 0xcc, 0xbe, 0x73, 0x47, 0x50, 0x9e, 0xff, 0x93, - 0x8b, 0xfd, 0x3f, 0x38, 0x65, 0xc4, 0xe9, 0xd7, 0x97, 0x1f, 0x3a, 0x99, - 0x47, 0x4f, 0x1d, 0x02, 0x47, 0x38, 0xde, 0xfe, 0x19, 0xd0, 0xb4, 0x59, - 0xd7, 0xec, 0x65, 0xae, 0xd3, 0xaf, 0xed, 0x80, 0xf8, 0x20, 0x3a, 0x9d, - 0x55, 0xc2, 0x43, 0x7e, 0x23, 0x19, 0xd2, 0x07, 0xcb, 0x7c, 0x93, 0xde, - 0x8f, 0x50, 0xeb, 0xcf, 0xd1, 0x3a, 0xff, 0x60, 0x06, 0x34, 0x80, 0x3a, - 0xdc, 0x3a, 0xf0, 0x63, 0x61, 0x3c, 0x0d, 0x18, 0x59, 0x3a, 0x88, 0xdf, - 0xad, 0x52, 0xd1, 0xa1, 0x3f, 0x42, 0xa2, 0xff, 0xf6, 0x02, 0x17, 0x9b, - 0xb7, 0x3d, 0xc0, 0x1d, 0x77, 0x20, 0xeb, 0x99, 0xd1, 0xd7, 0xec, 0x9c, - 0x82, 0x0c, 0x35, 0x9e, 0x45, 0x6f, 0xdc, 0xcd, 0xfe, 0xe7, 0x5f, 0x95, - 0x46, 0xde, 0x5a, 0x75, 0x78, 0x4c, 0x1e, 0x67, 0x5c, 0x3f, 0x09, 0x3d, - 0xf0, 0x33, 0x90, 0x75, 0xff, 0xcf, 0x82, 0xde, 0x60, 0x8b, 0xb0, 0x75, - 0x93, 0xa8, 0xa0, 0x14, 0x0f, 0x90, 0x5f, 0xf6, 0x03, 0x05, 0xc4, 0x2e, - 0x75, 0x6c, 0xeb, 0x1e, 0x5b, 0x2d, 0x08, 0x12, 0xcb, 0x70, 0xdd, 0x48, - 0x45, 0x4a, 0x51, 0x0e, 0xe6, 0x89, 0x0b, 0xf6, 0x49, 0x3b, 0x4e, 0x03, - 0x5c, 0x6f, 0x7c, 0x97, 0x9b, 0x0a, 0x9e, 0xc2, 0x78, 0x67, 0x44, 0xf5, - 0x1a, 0x67, 0xe7, 0x01, 0x83, 0x19, 0x9c, 0xe8, 0xf5, 0x3c, 0x9a, 0x5f, - 0xf6, 0x74, 0x5f, 0xed, 0xce, 0x1d, 0x7f, 0x0f, 0xb8, 0x08, 0x69, 0xd7, - 0xfa, 0x43, 0x8d, 0x6c, 0x68, 0xeb, 0xf4, 0x37, 0xc0, 0x10, 0xeb, 0xcd, - 0x7f, 0x4e, 0xbf, 0x79, 0x65, 0xae, 0xae, 0x55, 0x3a, 0x60, 0x98, 0x6c, - 0x85, 0x9c, 0x31, 0xf9, 0x47, 0x91, 0xcb, 0x48, 0xeb, 0xff, 0x94, 0x10, - 0xc7, 0x9c, 0xd2, 0x38, 0x9d, 0x7a, 0x79, 0x00, 0x75, 0x74, 0xf8, 0x56, - 0x87, 0x7f, 0xf6, 0xff, 0x0a, 0xf8, 0xe8, 0x30, 0x03, 0xad, 0xe4, 0xd1, - 0x02, 0xdb, 0xe6, 0xa0, 0x52, 0xc9, 0xf3, 0x78, 0xc0, 0xfd, 0xff, 0x92, - 0x7b, 0x89, 0xe6, 0x6f, 0x7d, 0x72, 0xaf, 0xf8, 0x7f, 0xa0, 0xef, 0xf4, - 0x60, 0xeb, 0xfc, 0x18, 0xd6, 0x60, 0xa8, 0x75, 0x39, 0xf5, 0xf0, 0xea, - 0xff, 0xf2, 0x29, 0xe0, 0x61, 0x4f, 0x1a, 0xf7, 0xd7, 0x3a, 0xff, 0x47, - 0x37, 0xd3, 0x8f, 0xce, 0xad, 0x22, 0x0b, 0xea, 0x17, 0xcd, 0xe6, 0x6c, - 0x75, 0xff, 0x3e, 0xeb, 0x8f, 0xe6, 0xff, 0x3a, 0xb7, 0x3d, 0xb1, 0x22, - 0xbf, 0xe7, 0x97, 0xc3, 0xce, 0xbb, 0x07, 0x5f, 0xff, 0xee, 0x3f, 0x7d, - 0xc9, 0xc9, 0xad, 0x60, 0xca, 0x07, 0xd3, 0xaf, 0xcf, 0x83, 0xf9, 0xe3, - 0xac, 0xb3, 0xa9, 0x66, 0xe0, 0x4a, 0x2f, 0x34, 0x20, 0x3a, 0xf6, 0xa3, - 0x7f, 0x06, 0xf2, 0x08, 0x2f, 0xff, 0xec, 0x1d, 0xb5, 0xa7, 0xf7, 0x38, - 0x9d, 0x86, 0x3e, 0x75, 0x01, 0x57, 0x06, 0xf0, 0xa3, 0xeb, 0xf2, 0xc8, - 0xb8, 0x73, 0xf8, 0x6a, 0xb0, 0x69, 0x4e, 0xb8, 0x04, 0x92, 0xe4, 0x2f, - 0xff, 0xfb, 0xbb, 0x62, 0x33, 0x10, 0xdd, 0x3a, 0xc1, 0xc7, 0x19, 0x1d, - 0x7c, 0x0e, 0x07, 0x63, 0xaf, 0xf0, 0x21, 0xb9, 0xb0, 0x44, 0xeb, 0x6c, - 0xe7, 0xab, 0x84, 0x77, 0x4f, 0xd8, 0x75, 0x61, 0xe0, 0xc1, 0x3d, 0xfd, - 0xf9, 0xe0, 0xf3, 0x24, 0x75, 0xfe, 0xeb, 0xfd, 0x3d, 0x76, 0x9d, 0x7b, - 0x61, 0x69, 0xd5, 0x3e, 0xaf, 0x7f, 0xbb, 0x8a, 0x11, 0x2d, 0xff, 0x93, - 0x85, 0x30, 0x56, 0x30, 0xfb, 0xd1, 0x07, 0xcc, 0x02, 0x65, 0x7f, 0x9a, - 0xce, 0x0c, 0x73, 0x0e, 0xbf, 0xd3, 0xa1, 0x90, 0x38, 0xec, 0x75, 0xf3, - 0x86, 0x7e, 0x43, 0xaf, 0xf2, 0x75, 0xf6, 0x8e, 0xc8, 0xeb, 0x7f, 0xa7, - 0xaf, 0xf2, 0x5b, 0xff, 0xdd, 0x90, 0xe4, 0xe1, 0xc7, 0xeb, 0xe8, 0xeb, - 0xfd, 0x0c, 0xf3, 0x17, 0x9a, 0x3a, 0xb0, 0xfe, 0xa7, 0x24, 0x5f, 0xc8, - 0xa7, 0xf3, 0x16, 0x75, 0xfb, 0x00, 0x9d, 0xd1, 0xd7, 0xbf, 0xfd, 0xce, - 0xbf, 0xfb, 0x79, 0x27, 0x3c, 0x2a, 0xce, 0x22, 0xce, 0xaf, 0x4f, 0x97, - 0xe3, 0xb7, 0x07, 0xa7, 0x56, 0x8d, 0xcc, 0xf1, 0x1d, 0x9f, 0x64, 0x74, - 0x31, 0x0c, 0x4a, 0x75, 0x52, 0x99, 0x08, 0xc4, 0x85, 0x17, 0x08, 0xff, - 0x18, 0xa5, 0xff, 0x85, 0x3c, 0xef, 0x93, 0xb7, 0x7f, 0x27, 0x5f, 0xfe, - 0x4c, 0xe8, 0x1d, 0x8c, 0xe3, 0xef, 0xa3, 0xaf, 0xbc, 0xbf, 0x7d, 0x3a, - 0xe8, 0xe9, 0xd7, 0xf7, 0xd3, 0x65, 0xbc, 0x8e, 0xa0, 0x1e, 0x17, 0x05, - 0x6e, 0xc5, 0x47, 0x5f, 0x7b, 0xe4, 0x5a, 0x75, 0xde, 0xc0, 0x9b, 0xbf, - 0x8b, 0xd3, 0xa2, 0x24, 0x2b, 0xb7, 0x6e, 0xc9, 0xd7, 0xef, 0x3f, 0xf5, - 0x78, 0x75, 0x2c, 0xf0, 0xbd, 0x18, 0xbd, 0x27, 0xd1, 0xd7, 0xff, 0x2f, - 0x4b, 0x70, 0x3f, 0x42, 0xfe, 0x9d, 0x7f, 0xe7, 0x81, 0xcf, 0xfd, 0x18, - 0xf9, 0xd4, 0xe8, 0xbe, 0xc2, 0x34, 0x1b, 0x0a, 0x25, 0x3a, 0xef, 0xb3, - 0x65, 0x62, 0xe2, 0xcc, 0x91, 0x19, 0x49, 0xd4, 0x3b, 0xff, 0x19, 0x15, - 0xfe, 0xea, 0x63, 0x19, 0xbf, 0xce, 0xbf, 0xfd, 0xac, 0x10, 0xcb, 0x98, - 0xb6, 0x62, 0x47, 0x5f, 0xe1, 0x53, 0x8e, 0xb5, 0x89, 0xd7, 0xe7, 0x67, - 0x32, 0x47, 0x56, 0x1e, 0xc7, 0x0c, 0xaf, 0xfe, 0x4e, 0x63, 0x28, 0xc8, - 0x55, 0x07, 0x47, 0x5f, 0x9d, 0x57, 0x1d, 0x93, 0xa9, 0xa7, 0xe1, 0xa4, - 0x7b, 0xff, 0x82, 0xca, 0x71, 0xf7, 0x6b, 0xb2, 0xe7, 0x5f, 0x81, 0x02, - 0xfc, 0x3a, 0xff, 0xfb, 0x5f, 0xd2, 0x7a, 0xed, 0xd6, 0x66, 0xff, 0x3a, - 0xc9, 0xc3, 0xf5, 0x60, 0x96, 0xff, 0xfd, 0xd0, 0xf7, 0xae, 0x38, 0xa2, - 0x73, 0x99, 0xe4, 0xeb, 0xf8, 0x61, 0x00, 0xe2, 0x75, 0xf6, 0xce, 0xa9, - 0xce, 0xbd, 0x38, 0x3c, 0x3a, 0xff, 0xe4, 0x5a, 0x6b, 0x8e, 0x9d, 0x0a, - 0xb9, 0xd4, 0xe8, 0x86, 0x42, 0x38, 0x1e, 0xbf, 0xe7, 0xf3, 0xf4, 0xea, - 0x7c, 0x27, 0x5f, 0xc1, 0xf3, 0xcc, 0xdf, 0x47, 0x5f, 0xff, 0xff, 0xba, - 0xff, 0x18, 0x92, 0x69, 0x94, 0xec, 0x9f, 0x5f, 0x7d, 0xdf, 0xce, 0x68, - 0xeb, 0xff, 0xff, 0xff, 0x6b, 0x59, 0xfe, 0x42, 0xf5, 0xde, 0xa6, 0xff, - 0x88, 0x53, 0x31, 0x90, 0xfd, 0xd8, 0xdd, 0xce, 0xa7, 0x4c, 0x7e, 0x21, - 0x07, 0x7d, 0xec, 0x6f, 0xa3, 0xae, 0x61, 0x83, 0xab, 0x46, 0xed, 0x82, - 0x3b, 0xf2, 0x72, 0x33, 0x85, 0x4c, 0x68, 0xaf, 0xfc, 0x81, 0xfb, 0x8c, - 0xa7, 0xcf, 0x56, 0x75, 0x3a, 0xf1, 0x03, 0x4c, 0xc1, 0x0a, 0x1d, 0xe1, - 0x22, 0xae, 0x44, 0xcc, 0x2e, 0xba, 0x50, 0xb5, 0x6e, 0x42, 0xbf, 0xd2, - 0xd9, 0xf8, 0xe4, 0x63, 0x4f, 0xd4, 0x21, 0x3e, 0x6d, 0x7e, 0x65, 0xd9, - 0xe3, 0x9d, 0x79, 0x86, 0x18, 0x2a, 0xf9, 0xbf, 0xc9, 0x15, 0x31, 0x7f, - 0x7e, 0xc0, 0x27, 0xba, 0x3d, 0xdf, 0xd5, 0xd3, 0xe5, 0x13, 0x1a, 0x74, - 0x66, 0xc4, 0x2b, 0x2d, 0xa3, 0xaf, 0xf7, 0xf7, 0x6f, 0x1c, 0x76, 0x3a, - 0xfd, 0xb2, 0xc3, 0xbf, 0xce, 0xae, 0x9f, 0x70, 0x88, 0x7c, 0xd2, 0xff, - 0x85, 0xd8, 0xd2, 0x0e, 0xed, 0x3a, 0xe7, 0x91, 0xd4, 0x27, 0x9b, 0x38, - 0xe2, 0x9d, 0x13, 0xc8, 0xf7, 0x7f, 0x0e, 0xfa, 0x67, 0x3e, 0x75, 0xff, - 0xef, 0xb3, 0x9d, 0xc8, 0x5b, 0xf1, 0x00, 0x75, 0xfc, 0x15, 0xe7, 0x37, - 0x83, 0xa8, 0x4f, 0xd7, 0x49, 0x17, 0xff, 0x90, 0x03, 0x1b, 0x8e, 0x7f, - 0x13, 0xd3, 0xaf, 0xe7, 0xff, 0x1b, 0xa0, 0x9d, 0x7f, 0xce, 0x3d, 0x74, - 0x6c, 0x68, 0xeb, 0xf6, 0xca, 0xe9, 0x9b, 0x9d, 0x7e, 0x4d, 0x3e, 0xcb, - 0x3d, 0x9f, 0xb7, 0xe7, 0x8e, 0xfa, 0x13, 0xd9, 0xfb, 0x74, 0x34, 0xf6, - 0x7e, 0xdf, 0x05, 0xb9, 0xa3, 0xd9, 0xfb, 0x40, 0x3d, 0x01, 0x22, 0xbf, - 0x3e, 0x6b, 0x04, 0xf6, 0x7e, 0xd1, 0xec, 0xfd, 0xba, 0x3e, 0x7b, 0x3f, - 0x56, 0x5b, 0xd9, 0xa2, 0x7f, 0x21, 0x48, 0xbe, 0xc9, 0xe4, 0xf4, 0xf6, - 0x7e, 0xd1, 0xec, 0xfd, 0xbb, 0xd7, 0x3d, 0x9f, 0xb7, 0xfd, 0x9e, 0xc7, - 0x72, 0x76, 0x00, 0xf6, 0x7e, 0xdf, 0xd9, 0xc4, 0xd0, 0x76, 0x3d, 0x9f, - 0xb5, 0xea, 0x28, 0xc4, 0x8f, 0x48, 0xd7, 0xdd, 0xd9, 0xfe, 0x7b, 0x3f, - 0x68, 0xf6, 0x7e, 0xe1, 0xaf, 0xb9, 0x86, 0x0f, 0x67, 0xed, 0x35, 0x58, - 0x70, 0x0d, 0x32, 0x10, 0x9b, 0xc2, 0x6b, 0xa4, 0xeb, 0x31, 0xd4, 0x2e, - 0xbe, 0xbe, 0xc1, 0x35, 0xf6, 0x35, 0xd4, 0x2d, 0x9f, 0xa9, 0x91, 0x21, - 0x7f, 0xec, 0x90, 0x33, 0xac, 0x47, 0x19, 0x3a, 0xe6, 0xec, 0x55, 0xf3, - 0x31, 0x1d, 0x3a, 0xb6, 0x45, 0xce, 0xe8, 0x42, 0x7e, 0xa8, 0x5e, 0xba, - 0xb9, 0x85, 0x13, 0x90, 0x57, 0xff, 0xe6, 0xf5, 0xe7, 0x43, 0x2e, 0x0e, - 0x3a, 0xe1, 0x93, 0xaf, 0xf2, 0xa8, 0xd2, 0x69, 0x9c, 0x3a, 0xb7, 0x44, - 0x5f, 0x55, 0xe9, 0xd9, 0x0b, 0xcd, 0x8c, 0xcb, 0x08, 0x52, 0x14, 0x6a, - 0xe4, 0x3d, 0x47, 0xe1, 0x6c, 0x4e, 0x7b, 0x86, 0x17, 0x17, 0xff, 0xfc, - 0x9c, 0x8e, 0x3b, 0x66, 0xcf, 0x5d, 0xba, 0x07, 0x1f, 0xa7, 0x5f, 0xf9, - 0x47, 0xdc, 0x5f, 0x9c, 0x0c, 0x8e, 0xbf, 0xfc, 0x0e, 0xbe, 0x0e, 0x35, - 0x39, 0x93, 0x8e, 0xbf, 0x86, 0x14, 0xe4, 0x34, 0xeb, 0xcc, 0x30, 0xc1, - 0x57, 0xbc, 0xbf, 0xa5, 0x4c, 0x5f, 0xdf, 0xf4, 0x37, 0xcf, 0x72, 0x74, - 0x74, 0xeb, 0xff, 0xf7, 0x31, 0xbe, 0x44, 0x73, 0x66, 0x5a, 0xfd, 0xd8, - 0xea, 0x14, 0x49, 0xfc, 0xee, 0xf9, 0xaf, 0xee, 0xe7, 0x5f, 0xde, 0xb8, - 0xe6, 0xff, 0x3a, 0xf0, 0xc7, 0xbe, 0x0f, 0x43, 0xc9, 0x1d, 0xe9, 0xcf, - 0xd3, 0xa9, 0xaa, 0xaf, 0xc0, 0xcd, 0x87, 0xeb, 0x48, 0xf5, 0x2c, 0x61, - 0x83, 0xf7, 0x29, 0xc6, 0xf7, 0x80, 0x9b, 0x1d, 0x6f, 0x4e, 0xbf, 0xf2, - 0x7f, 0x99, 0xaf, 0x1f, 0x4d, 0x8e, 0xbf, 0xe1, 0x40, 0xcf, 0xda, 0x9e, - 0x7f, 0x9d, 0x4d, 0x44, 0x87, 0x04, 0x45, 0x02, 0xf3, 0x0c, 0x30, 0x58, - 0x84, 0x17, 0xee, 0xca, 0x22, 0x45, 0x88, 0x41, 0x31, 0xad, 0xbc, 0xc3, - 0x0c, 0x16, 0x20, 0xf5, 0x16, 0x20, 0xf4, 0xc6, 0xb6, 0xcb, 0xc4, 0x4d, - 0xc9, 0xca, 0xff, 0xee, 0x3b, 0x53, 0xf9, 0xc9, 0x3a, 0xce, 0xa7, 0x3e, - 0xa9, 0xc5, 0x17, 0xff, 0xb3, 0x89, 0xde, 0x46, 0x69, 0x23, 0x63, 0xaf, - 0x9f, 0xee, 0xb3, 0xa9, 0x67, 0xcf, 0xf4, 0x7b, 0xf9, 0x88, 0x00, 0x63, - 0xc9, 0xd7, 0xc2, 0x8e, 0xa1, 0xd7, 0xbc, 0xbf, 0xa7, 0x56, 0xc6, 0xf9, - 0x64, 0x17, 0xe9, 0x3f, 0x1d, 0x65, 0x5f, 0x86, 0x04, 0x70, 0xab, 0xb2, - 0x45, 0x5c, 0xc3, 0x05, 0x56, 0x1f, 0xb6, 0x89, 0xbe, 0x46, 0xc0, 0xad, - 0xfe, 0x1f, 0x2f, 0xef, 0x31, 0x51, 0x53, 0x1b, 0xca, 0x74, 0xea, 0xb0, - 0x89, 0x1b, 0x62, 0x1a, 0x97, 0xff, 0x3f, 0xba, 0xcc, 0x04, 0x0c, 0x28, - 0x75, 0xff, 0xf3, 0x74, 0xc3, 0xf7, 0x8e, 0x9c, 0x71, 0x43, 0xaf, 0xff, - 0xb4, 0x39, 0xbf, 0xb1, 0xa8, 0xea, 0x6f, 0xe9, 0xd5, 0xba, 0x27, 0x98, - 0x4d, 0xae, 0x26, 0x0b, 0x10, 0xe0, 0xbf, 0x92, 0x40, 0xc8, 0xf4, 0xeb, - 0xff, 0xff, 0x3e, 0xd3, 0x6b, 0xfa, 0xdf, 0xc0, 0x30, 0x0f, 0x1d, 0xc1, - 0xf4, 0xeb, 0xf2, 0xf4, 0xc4, 0x6e, 0x75, 0xb4, 0x04, 0x4c, 0xf9, 0x70, - 0xbf, 0xb1, 0x96, 0xa7, 0x74, 0x75, 0x3a, 0xfa, 0x18, 0x1e, 0x72, 0x15, - 0x89, 0x1b, 0x0f, 0x65, 0x1a, 0x44, 0x68, 0x82, 0x51, 0xa8, 0x62, 0xfc, - 0xae, 0xf3, 0x0c, 0x30, 0x55, 0xf7, 0xb0, 0x20, 0x2a, 0x62, 0xfe, 0xfb, - 0x89, 0x0d, 0x3a, 0xff, 0x87, 0xfa, 0x4e, 0xf5, 0x16, 0x75, 0xef, 0x0a, - 0x4f, 0x1d, 0x7b, 0xf0, 0x03, 0xab, 0xa6, 0xf7, 0x44, 0x57, 0xf7, 0x9c, - 0xee, 0x63, 0x27, 0x53, 0x53, 0x14, 0x01, 0x8e, 0x10, 0x23, 0xa6, 0x88, - 0x6f, 0xff, 0x87, 0x7f, 0x1b, 0xfa, 0xe3, 0x28, 0xd8, 0x60, 0xeb, 0xff, - 0xff, 0xfe, 0xfe, 0xbc, 0xeb, 0xc7, 0x21, 0x3e, 0x9c, 0x92, 0x78, 0x6a, - 0x72, 0x07, 0xed, 0xce, 0xe1, 0xd7, 0xff, 0x4c, 0x01, 0x70, 0xcb, 0x14, - 0x4e, 0x9d, 0x76, 0x30, 0x75, 0xb1, 0xcf, 0x6b, 0x48, 0x97, 0xca, 0xb9, - 0xec, 0xe3, 0xa9, 0xa7, 0x9b, 0x04, 0xd7, 0xff, 0x67, 0x7d, 0x5a, 0x6b, - 0xce, 0x9f, 0x0e, 0xbd, 0x0a, 0xfa, 0x3a, 0x9a, 0x7c, 0x70, 0x8b, 0x78, - 0x18, 0xb3, 0xaf, 0xbd, 0xfe, 0x7a, 0x75, 0x21, 0xbe, 0xe8, 0xdd, 0xff, - 0x4b, 0x82, 0xfb, 0xa3, 0xf0, 0xea, 0x75, 0x62, 0x6d, 0x49, 0xc5, 0x28, - 0x8c, 0xf8, 0x61, 0x08, 0x15, 0xff, 0x24, 0x17, 0xfe, 0x84, 0x00, 0x7f, - 0xad, 0xb1, 0x83, 0xaf, 0xda, 0xc5, 0x1f, 0x47, 0x5f, 0xca, 0xfa, 0x41, - 0xdd, 0xa7, 0x5f, 0xfa, 0x3b, 0x3c, 0x9c, 0xc8, 0xdf, 0xd3, 0xaf, 0xff, - 0xc9, 0xf7, 0x5e, 0x6f, 0xf7, 0x5f, 0x9e, 0xc7, 0xa7, 0x5f, 0x20, 0xc0, - 0x0e, 0xbf, 0xed, 0x3f, 0x7e, 0xf3, 0x01, 0x0e, 0xa6, 0xa2, 0xb8, 0x0a, - 0xfa, 0x1f, 0xbf, 0xfd, 0xa4, 0xeb, 0xb7, 0x8e, 0xc8, 0x85, 0x43, 0xae, - 0x94, 0xf1, 0xd7, 0xf2, 0x9f, 0x7e, 0x3e, 0x8e, 0xbf, 0xb8, 0x9b, 0xea, - 0x37, 0x3a, 0x9a, 0x7e, 0x88, 0x33, 0xe9, 0x6d, 0xff, 0x86, 0x19, 0xe4, - 0x77, 0xa8, 0x03, 0xaf, 0xbc, 0x01, 0x04, 0xea, 0x6a, 0xac, 0x2c, 0x27, - 0x91, 0x82, 0x43, 0xbd, 0x93, 0x0e, 0xc2, 0xf9, 0x65, 0xec, 0x1e, 0xdd, - 0xef, 0xce, 0xbe, 0xef, 0x73, 0x47, 0x5d, 0x8c, 0x9d, 0x66, 0xec, 0x79, - 0xd0, 0x2f, 0xe4, 0x86, 0xfd, 0xd0, 0x66, 0x09, 0xd7, 0xff, 0x2b, 0xa6, - 0x71, 0xe7, 0x6b, 0x8f, 0xb9, 0xd5, 0x07, 0xdb, 0xa2, 0x5b, 0xfe, 0xc1, - 0xee, 0x6b, 0x13, 0x87, 0x5f, 0xff, 0x37, 0xe3, 0x91, 0xf1, 0xcf, 0xff, - 0x18, 0x3a, 0xff, 0xf7, 0xf5, 0x8c, 0xf1, 0xe7, 0x67, 0x38, 0xe7, 0x5f, - 0xdc, 0x02, 0x4e, 0x70, 0x1d, 0x58, 0x7f, 0x30, 0x97, 0x7d, 0x9f, 0x4d, - 0x1d, 0x7f, 0x2b, 0x2c, 0x8c, 0xf9, 0xb0, 0x4e, 0xad, 0x1e, 0xcf, 0xc8, - 0x28, 0x09, 0xdb, 0xc8, 0x87, 0x73, 0x51, 0x86, 0x37, 0xde, 0x6f, 0xff, - 0x93, 0x58, 0x0f, 0xe9, 0x14, 0xe4, 0x0a, 0x1d, 0x7f, 0xe8, 0x57, 0xf4, - 0x3a, 0x41, 0xdd, 0xa7, 0x5f, 0xff, 0xdf, 0xce, 0x23, 0xfd, 0x3d, 0x76, - 0xcc, 0xc3, 0x0c, 0x15, 0x7f, 0xb8, 0x18, 0x58, 0x21, 0x67, 0x50, 0xa2, - 0x43, 0xeb, 0xd7, 0xc0, 0xcc, 0x50, 0xab, 0xe8, 0xf6, 0x3e, 0x75, 0xff, - 0x76, 0x25, 0xe3, 0x8f, 0xe4, 0x4e, 0xbc, 0x17, 0xe9, 0xd7, 0x7f, 0x40, - 0x3d, 0x66, 0x4e, 0xef, 0x34, 0x42, 0x68, 0x86, 0x6f, 0x30, 0xc3, 0x05, - 0x5e, 0xc1, 0x91, 0x53, 0x17, 0xf7, 0xfe, 0xcd, 0xb0, 0x10, 0xd1, 0x7d, - 0x8e, 0xaf, 0x4f, 0x9c, 0x4a, 0xaf, 0xa0, 0x55, 0xba, 0x7f, 0x3a, 0xff, - 0x34, 0x73, 0xff, 0x0e, 0xc7, 0x5e, 0x85, 0x77, 0x3a, 0xfd, 0x80, 0xe4, - 0x2b, 0x9d, 0x4e, 0xa9, 0x7b, 0x62, 0x20, 0x10, 0xe3, 0xbe, 0xe5, 0xfd, - 0x85, 0x77, 0x08, 0xa0, 0xb0, 0x26, 0x73, 0x87, 0x6f, 0xf3, 0xaf, 0x13, - 0xac, 0xb4, 0xeb, 0xe4, 0xfa, 0x39, 0xd7, 0xff, 0xee, 0x47, 0x75, 0x88, - 0x31, 0xfd, 0x30, 0xe2, 0x75, 0xf8, 0x09, 0xd7, 0xf9, 0xd7, 0xff, 0x69, - 0xd4, 0xd2, 0xdf, 0x5e, 0xa4, 0x8e, 0xbf, 0xc1, 0xce, 0xfb, 0xea, 0x09, - 0xd7, 0xfe, 0xc5, 0xa0, 0x3b, 0x80, 0x85, 0x9d, 0x7d, 0x8b, 0xf2, 0x03, - 0xab, 0x87, 0xbe, 0x27, 0x97, 0xff, 0x90, 0x1c, 0xf3, 0xac, 0xec, 0xa2, - 0x24, 0x68, 0x83, 0x2f, 0x83, 0xcc, 0x91, 0xd4, 0xd3, 0xf8, 0x9e, 0x57, - 0xbd, 0xc0, 0xab, 0x9d, 0x7f, 0xfb, 0xb1, 0x3b, 0x06, 0x5c, 0x4f, 0x7c, - 0xfc, 0xea, 0x74, 0x48, 0xcf, 0xc4, 0xa1, 0x1f, 0xad, 0xd5, 0x1a, 0xf1, - 0x17, 0x50, 0x92, 0xfc, 0x65, 0x57, 0xfc, 0xb4, 0x63, 0x04, 0x1c, 0x73, - 0xae, 0xe0, 0x4e, 0xbf, 0xff, 0x35, 0x04, 0x1c, 0xcd, 0xfc, 0xc0, 0xfc, - 0x40, 0x75, 0xe4, 0x61, 0x5c, 0xeb, 0xfd, 0x93, 0xb5, 0xff, 0xba, 0xce, - 0xae, 0x9e, 0x9f, 0x07, 0xeb, 0x13, 0x17, 0x43, 0x76, 0x45, 0xb5, 0x0a, - 0x8b, 0xfd, 0x3d, 0x9a, 0x9e, 0xce, 0xb9, 0xd7, 0xff, 0xc2, 0xf2, 0xf1, - 0xdc, 0x40, 0xcf, 0xd8, 0xab, 0x0e, 0xa6, 0xae, 0x7e, 0x00, 0x7f, 0x14, - 0x92, 0x52, 0xde, 0xa3, 0x62, 0xfa, 0x12, 0xa3, 0x7b, 0xfa, 0x76, 0x0a, - 0x2a, 0x73, 0xaf, 0xf8, 0x3f, 0xf4, 0x2b, 0x7c, 0xf9, 0xd7, 0xff, 0x87, - 0x6f, 0x0c, 0xa0, 0xe0, 0x30, 0x54, 0x3a, 0xf7, 0x9c, 0x73, 0xa9, 0xcf, - 0x9e, 0x12, 0xef, 0x3f, 0x59, 0x3a, 0xbc, 0x36, 0x26, 0x6f, 0x2c, 0x04, - 0x10, 0xcb, 0xc9, 0x4b, 0x72, 0x50, 0xdd, 0x35, 0x25, 0x98, 0x72, 0x12, - 0x71, 0x3a, 0x5d, 0xeb, 0xa0, 0x97, 0x06, 0x14, 0x13, 0xc4, 0x17, 0xb7, - 0xda, 0x71, 0xd7, 0xfb, 0x7f, 0x12, 0xe3, 0xee, 0xa8, 0xeb, 0xf4, 0x2e, - 0x33, 0x47, 0x5f, 0xff, 0x49, 0xf5, 0xa7, 0x5e, 0x7d, 0x35, 0xc8, 0x3a, - 0xff, 0x08, 0xbb, 0x56, 0xe8, 0x75, 0xfe, 0xfa, 0x4e, 0x4f, 0xb5, 0xca, - 0xb2, 0xce, 0xbf, 0xb0, 0x54, 0xeb, 0xcc, 0x87, 0x87, 0xe4, 0xce, 0xb1, - 0x30, 0x54, 0x4d, 0xd3, 0x95, 0xf7, 0x43, 0xbb, 0x4e, 0xbf, 0xc2, 0xd1, - 0xc5, 0xbc, 0x8e, 0xbc, 0xb0, 0x61, 0xd4, 0xe7, 0xdd, 0x84, 0x70, 0x61, - 0x7a, 0x78, 0x3f, 0x3a, 0xff, 0xf7, 0xdd, 0x68, 0x0c, 0x15, 0x38, 0xeb, - 0x3a, 0xa4, 0x7c, 0xff, 0x1f, 0xbf, 0x7f, 0xfa, 0x8f, 0x4e, 0xbf, 0x3a, - 0xff, 0x92, 0x3a, 0xe4, 0xd8, 0xea, 0x43, 0xe4, 0xe1, 0x47, 0xc9, 0xaf, - 0xcc, 0x20, 0x15, 0x21, 0xd7, 0xfd, 0x9f, 0xe6, 0x2c, 0x63, 0xe7, 0x5f, - 0xd3, 0x93, 0xbb, 0xba, 0xb9, 0xd6, 0x10, 0x1f, 0x46, 0x1b, 0x5f, 0x96, - 0xf2, 0xd8, 0x07, 0x5f, 0xbb, 0xea, 0xd3, 0x47, 0x5d, 0xfd, 0x61, 0xe8, - 0x79, 0x28, 0xa7, 0x45, 0x28, 0x5d, 0xad, 0xa3, 0xaf, 0xe7, 0xdb, 0x05, - 0x14, 0x3a, 0xba, 0x6f, 0x34, 0x21, 0x7f, 0xf3, 0x8c, 0x71, 0xfd, 0x9b, - 0xba, 0xd1, 0x54, 0x04, 0x61, 0xe2, 0xf2, 0xc8, 0x6f, 0xf4, 0x03, 0x5a, - 0x7e, 0xb4, 0xeb, 0x83, 0xb1, 0xd7, 0xfb, 0x76, 0xef, 0xa4, 0xfb, 0x9d, - 0x79, 0x37, 0xd1, 0xd5, 0x87, 0xa0, 0x86, 0x94, 0x88, 0x87, 0xe3, 0x3d, - 0xd9, 0x23, 0xaf, 0x77, 0x34, 0x77, 0xcb, 0x5b, 0xff, 0xe0, 0x78, 0x84, - 0xcd, 0x3e, 0xd8, 0x28, 0xa1, 0xd7, 0xfb, 0xab, 0x7d, 0xff, 0x12, 0x3a, - 0xb1, 0x10, 0x48, 0x9f, 0x7f, 0x3b, 0x28, 0xb7, 0x64, 0xeb, 0xb1, 0x83, - 0xa8, 0xab, 0xfb, 0x5e, 0x5f, 0xae, 0xb2, 0xa8, 0xaa, 0x2a, 0x8a, 0xa2, - 0xa9, 0xa7, 0xc0, 0x81, 0x5e, 0x97, 0x04, 0x2a, 0x78, 0x29, 0x50, 0x55, - 0xdc, 0xc2, 0xaf, 0xe8, 0x8f, 0xb2, 0xeb, 0x2b, 0xc1, 0x6b, 0x69, 0xf8, - 0xaa, 0x2a, 0x8a, 0xa6, 0x96, 0x88, 0x15, 0x45, 0x51, 0x54, 0x55, 0x15, - 0x45, 0x51, 0x55, 0xb1, 0xbc, 0x00, 0x52, 0x05, 0x7a, 0x15, 0xa0, 0xa9, - 0xc1, 0x54, 0x55, 0x15, 0x4d, 0x2d, 0x34, 0x15, 0x45, 0x51, 0x54, 0x55, - 0x15, 0x4d, 0x35, 0x1e, 0x85, 0x7c, 0x29, 0x50, 0x55, 0x15, 0x45, 0x51, - 0x54, 0x55, 0x6c, 0x6a, 0x14, 0x0a, 0xe8, 0x57, 0x02, 0xac, 0xa1, 0x54, - 0x55, 0x15, 0x45, 0x51, 0x54, 0x03, 0x51, 0xb8, 0x57, 0xa1, 0x41, 0x0a, - 0xa2, 0xa8, 0xaa, 0x2a, 0xfd, 0xc7, 0xf7, 0x58, 0x55, 0x15, 0x4d, 0x3c, - 0xf9, 0x05, 0x70, 0x2a, 0x02, 0xbd, 0x27, 0xb4, 0x8a, 0xa2, 0xa8, 0xaa, - 0x2a, 0x8a, 0xa6, 0x9a, 0x8d, 0xc2, 0x90, 0x2a, 0x70, 0x55, 0x15, 0x45, - 0x51, 0x54, 0x55, 0x34, 0xd4, 0x00, 0x2b, 0x81, 0x42, 0x15, 0x6e, 0x15, - 0x45, 0x51, 0x56, 0x69, 0x54, 0x56, 0xe5, 0x85, 0x15, 0x45, 0x51, 0x54, - 0x55, 0x6c, 0x7c, 0xcd, 0x0a, 0x50, 0x6a, 0x43, 0x4c, 0x85, 0x7a, 0x15, - 0xf0, 0xab, 0x61, 0x54, 0x55, 0x15, 0x66, 0x95, 0x45, 0x6e, 0x58, 0x51, - 0x54, 0x55, 0x39, 0xe9, 0x34, 0x29, 0x06, 0xba, 0x34, 0xb0, 0xaa, 0x2a, - 0x8a, 0xa2, 0xa8, 0xaa, 0x2a, 0x9c, 0xd9, 0x6e, 0x15, 0xd0, 0xa5, 0x85, - 0x08, 0x55, 0x15, 0x45, 0x51, 0x55, 0xd2, 0xfb, 0x41, 0x5f, 0x0a, 0xa2, - 0xa8, 0xaa, 0x2a, 0x96, 0x5f, 0x08, 0x57, 0xc2, 0xac, 0xb2, 0xa8, 0xaa, - 0x2a, 0xbd, 0x2d, 0x02, 0x15, 0x45, 0x51, 0x54, 0x55, 0x15, 0x4e, 0x6a, - 0x19, 0x0a, 0xe0, 0x50, 0x42, 0xa9, 0xd7, 0xea, 0x36, 0x70, 0x69, 0xe8, - 0x0a, 0x71, 0x6e, 0x4d, 0x9b, 0xa4, 0x23, 0x32, 0xb9, 0xeb, 0x27, 0x3d, - 0x84, 0x62, 0xd2, 0x78, 0x71, 0x0c, 0xbe, 0x9d, 0x0b, 0xb6, 0x99, 0xfe, - 0xc2, 0x17, 0x99, 0xcc, 0xac, 0x25, 0xcf, 0x16, 0x79, 0x24, 0x54, 0x93, - 0x7e, 0x68, 0xbe, 0x68, 0xa9, 0x93, 0x55, 0xbc, 0x8e, 0xb2, 0xaf, 0x92, - 0x51, 0xd3, 0xaf, 0x20, 0x30, 0xeb, 0x4d, 0xba, 0x23, 0x7a, 0x73, 0xc1, - 0xaf, 0x90, 0x59, 0xe7, 0x32, 0x91, 0x7c, 0xd2, 0x80, 0x2f, 0xf7, 0x11, - 0x80, 0x75, 0xf6, 0x3a, 0xf2, 0x4e, 0x9f, 0x8e, 0xad, 0xd1, 0x1e, 0xc9, - 0xcf, 0xcd, 0x2f, 0xd9, 0x8c, 0xc7, 0x93, 0xae, 0xf5, 0xce, 0xbf, 0xbb, - 0x03, 0xe5, 0xfd, 0x3a, 0xe8, 0xe9, 0xd6, 0x43, 0xa4, 0x5a, 0xda, 0x47, - 0x59, 0x67, 0x5d, 0x3d, 0x32, 0x22, 0x5f, 0xa2, 0xdc, 0x43, 0x81, 0xef, - 0x22, 0x17, 0xfd, 0xc7, 0x5e, 0x32, 0xe3, 0xb1, 0xd5, 0x88, 0x92, 0xf5, - 0x6a, 0xff, 0xe1, 0x17, 0xd8, 0x71, 0x27, 0x3c, 0xf1, 0xd7, 0x9f, 0x7d, - 0x1d, 0x50, 0x7c, 0x3a, 0x45, 0xbd, 0x1d, 0x73, 0xaf, 0xc9, 0x3d, 0x03, - 0xe9, 0xd4, 0xd3, 0xc3, 0x58, 0xd5, 0xff, 0x79, 0x80, 0x6b, 0x16, 0xea, - 0xe7, 0x5e, 0xcd, 0xd8, 0x3a, 0xf6, 0xfe, 0xe7, 0x4f, 0x64, 0x4f, 0x2f, - 0xa7, 0x67, 0x5a, 0x75, 0xe0, 0x40, 0x9d, 0x48, 0x6f, 0x60, 0x8e, 0xff, - 0xf9, 0xfc, 0x47, 0x7b, 0x1e, 0xbc, 0xcc, 0x30, 0xc1, 0xd4, 0xe9, 0xb0, - 0x43, 0xde, 0x9c, 0x42, 0x3f, 0x53, 0xeb, 0x6c, 0xa8, 0xe4, 0x1b, 0x1c, - 0xb6, 0x32, 0xa0, 0x42, 0x77, 0x21, 0x27, 0x28, 0x43, 0x6e, 0x5c, 0x91, - 0xfc, 0xab, 0x97, 0xb3, 0x0b, 0x9e, 0x9b, 0xae, 0x15, 0x9c, 0x21, 0x8a, - 0x58, 0x0f, 0xa6, 0x43, 0x1a, 0x8e, 0xa1, 0x09, 0xf8, 0xf1, 0x2f, 0x90, - 0x64, 0xe7, 0x5f, 0xff, 0xb5, 0xde, 0xa3, 0x3a, 0xeb, 0xfd, 0x24, 0x80, - 0x3a, 0x96, 0x7e, 0x8c, 0x0f, 0xdf, 0xef, 0xb8, 0x65, 0xc4, 0xe9, 0xd7, - 0xf2, 0xf4, 0x8a, 0x7d, 0x83, 0xaf, 0xcf, 0xbf, 0x1d, 0xa7, 0x50, 0xa2, - 0x23, 0xc9, 0x92, 0xa2, 0xfb, 0xb7, 0xf9, 0xd7, 0xef, 0xc0, 0x87, 0x0e, - 0xbf, 0xda, 0xc5, 0xa7, 0xf9, 0x07, 0x59, 0xf0, 0xfb, 0x44, 0x5f, 0xe4, - 0xb7, 0xf6, 0xfa, 0x75, 0x5d, 0x73, 0xaf, 0xe6, 0x8a, 0x37, 0x98, 0x75, - 0xfb, 0x64, 0xeb, 0xb4, 0xea, 0xe9, 0xe9, 0x09, 0x5d, 0xf6, 0x01, 0x14, - 0x3a, 0xff, 0xdc, 0x7e, 0xfa, 0x38, 0xc4, 0x7a, 0x75, 0xec, 0xc6, 0x4e, - 0xb6, 0x70, 0xf6, 0xbd, 0x3f, 0xbf, 0x83, 0xd0, 0xae, 0x04, 0xeb, 0xe5, - 0xbe, 0x6c, 0x75, 0xfb, 0x27, 0x0b, 0xee, 0x75, 0x21, 0xe4, 0xe8, 0x86, - 0xf9, 0xc7, 0xf2, 0x3a, 0xcf, 0x89, 0xbd, 0x74, 0x84, 0x5e, 0xf4, 0x51, - 0xf7, 0x59, 0xe2, 0x1b, 0xfb, 0x58, 0xb4, 0xe3, 0x9d, 0x7b, 0x76, 0xe8, - 0xeb, 0x3e, 0xe7, 0x91, 0xd2, 0xbb, 0xe0, 0xc7, 0x5a, 0x75, 0xf3, 0x86, - 0x7e, 0xd1, 0x57, 0xe6, 0xcc, 0xc3, 0x0c, 0x1d, 0x42, 0x7a, 0x41, 0x26, - 0xbe, 0x8f, 0xaf, 0xe7, 0x50, 0x11, 0x6b, 0x8e, 0x7e, 0x90, 0xd3, 0xae, - 0x95, 0xa4, 0x2a, 0xd7, 0x0a, 0x08, 0x32, 0xf6, 0x3f, 0xb1, 0x85, 0x30, - 0x61, 0xbb, 0x79, 0x5a, 0x56, 0xf9, 0xf4, 0xeb, 0xcd, 0x18, 0x3a, 0xdb, - 0xab, 0x47, 0x8e, 0xe5, 0xb7, 0xf3, 0xf7, 0x67, 0xee, 0xc7, 0x5f, 0x83, - 0xee, 0x0c, 0x8e, 0xbd, 0xd7, 0x64, 0xeb, 0xe4, 0x18, 0x64, 0xeb, 0xfd, - 0xfc, 0xf2, 0xec, 0xa6, 0x8e, 0xa6, 0xa3, 0x17, 0xa5, 0xcb, 0x27, 0xe0, - 0xe4, 0xe2, 0x0b, 0xfe, 0x74, 0xe3, 0xaf, 0x6c, 0x60, 0xeb, 0xf9, 0xf8, - 0x9b, 0x40, 0x9d, 0x7f, 0xdb, 0x0e, 0x37, 0x99, 0xee, 0x8e, 0xbf, 0xf6, - 0x0e, 0xed, 0xd7, 0x42, 0xfe, 0x9d, 0x7e, 0xcf, 0xeb, 0x14, 0x3a, 0x90, - 0xf9, 0x96, 0x7f, 0x78, 0x0f, 0x38, 0xeb, 0xff, 0xec, 0x11, 0x76, 0x00, - 0x2f, 0xbb, 0x50, 0x4e, 0xbf, 0xfd, 0x1e, 0x19, 0x6b, 0xf7, 0x6f, 0x0c, - 0x67, 0x0e, 0xa0, 0x22, 0xe7, 0x83, 0xa2, 0x99, 0x7f, 0xcb, 0xe6, 0x7f, - 0x03, 0xdd, 0x8e, 0xbf, 0xfe, 0xe3, 0xae, 0x4f, 0xfc, 0xec, 0xa2, 0x24, - 0x68, 0xbe, 0x2f, 0x47, 0x76, 0x34, 0x5f, 0xf4, 0xe8, 0x83, 0x92, 0xd5, - 0xef, 0x5d, 0x51, 0xd7, 0xff, 0xf3, 0x60, 0x12, 0xe2, 0x0e, 0x4e, 0x86, - 0xe9, 0x00, 0x75, 0xff, 0x95, 0x26, 0x08, 0x14, 0x4c, 0xe9, 0xd7, 0xf4, - 0x77, 0x76, 0xe7, 0xce, 0xbf, 0xf7, 0xf4, 0x9d, 0xf8, 0x86, 0x1a, 0x75, - 0xe8, 0xdd, 0x51, 0xd7, 0xf4, 0x7f, 0x4f, 0x9b, 0x1d, 0x4e, 0x8b, 0x4c, - 0x2d, 0x9c, 0x7a, 0xc0, 0xf5, 0xff, 0xda, 0xc1, 0xfe, 0xbc, 0xce, 0x7c, - 0xdc, 0xeb, 0xfe, 0x63, 0xce, 0xda, 0xc5, 0xba, 0xb9, 0xd7, 0x93, 0x88, - 0x75, 0xfb, 0x1b, 0xd0, 0x34, 0xeb, 0xff, 0xa7, 0x7d, 0x47, 0x16, 0xe7, - 0x11, 0x67, 0x5d, 0xb7, 0xce, 0xbf, 0xd3, 0xb9, 0x0d, 0x7c, 0x13, 0xa9, - 0xcf, 0x27, 0x05, 0xef, 0xec, 0x63, 0xcf, 0x23, 0xe7, 0x5f, 0xff, 0xbf, - 0xe5, 0xaf, 0x39, 0x07, 0xde, 0xa3, 0xaf, 0x0a, 0xbe, 0xe7, 0x9d, 0xfe, - 0x75, 0xed, 0x99, 0x57, 0x3a, 0xb6, 0x46, 0x66, 0x17, 0xc9, 0x5c, 0x24, - 0xb7, 0x7f, 0x0e, 0xbf, 0x75, 0x36, 0x85, 0x9a, 0x61, 0x3b, 0xef, 0x85, - 0xe0, 0xd3, 0x09, 0xdd, 0xeb, 0x9a, 0x81, 0x3b, 0xfc, 0x30, 0xa7, 0xdf, - 0xbe, 0x9a, 0x81, 0x3b, 0xfd, 0xac, 0xe2, 0x68, 0x3b, 0x1a, 0x61, 0x3b, - 0xb0, 0x06, 0x98, 0x4e, 0xe6, 0x18, 0x3c, 0xc2, 0x75, 0x89, 0xa5, 0xee, - 0x68, 0x85, 0xab, 0x23, 0xd2, 0x04, 0xe4, 0x06, 0x08, 0xad, 0xf2, 0xcc, - 0x26, 0x98, 0xf9, 0xec, 0x9b, 0xa7, 0xee, 0xc4, 0x78, 0xf4, 0xeb, 0x8b, - 0xe8, 0x7f, 0xc1, 0xa8, 0x27, 0x18, 0x47, 0x6a, 0x1d, 0x9f, 0x94, 0x69, - 0x78, 0x7d, 0x59, 0xd7, 0xfc, 0xe1, 0xf8, 0xa4, 0xef, 0x2b, 0x3a, 0xf0, - 0xe6, 0xb0, 0xf5, 0xfa, 0x39, 0x78, 0x1e, 0xb2, 0x75, 0x3b, 0x27, 0xbb, - 0x68, 0x4f, 0x82, 0x1b, 0x58, 0x5f, 0x28, 0x5e, 0x21, 0x13, 0x23, 0xdd, - 0x5a, 0xe4, 0x3c, 0xb4, 0x7d, 0xf9, 0xca, 0x69, 0xd0, 0xcb, 0xf2, 0x63, - 0x7e, 0x06, 0x75, 0x14, 0x3a, 0xfe, 0xe3, 0xf9, 0x1d, 0xfd, 0x3a, 0xfe, - 0x7f, 0xe3, 0x28, 0xb3, 0xaf, 0xcf, 0x39, 0xc7, 0xe7, 0x5f, 0x92, 0x77, - 0xd3, 0x63, 0xaf, 0xd0, 0xdf, 0xe4, 0x8e, 0xbf, 0x0e, 0x79, 0xc6, 0x4e, - 0xbf, 0xfd, 0x9e, 0xeb, 0x89, 0xe3, 0x76, 0xbe, 0x6c, 0x75, 0xff, 0x72, - 0x17, 0xc4, 0x7d, 0xda, 0x75, 0xfd, 0xe4, 0x5b, 0x3d, 0x1b, 0x1d, 0x4d, - 0x45, 0xba, 0x26, 0xfa, 0x71, 0x5b, 0x27, 0x62, 0x02, 0xc9, 0x13, 0xf4, - 0xa4, 0x49, 0xbf, 0x0d, 0xfb, 0xff, 0x64, 0x71, 0x94, 0x1e, 0x66, 0xe7, - 0x5f, 0x0b, 0xe3, 0x07, 0x53, 0xb3, 0x8e, 0x76, 0x4c, 0x01, 0xc6, 0x52, - 0x86, 0x52, 0x1b, 0x4a, 0xe4, 0xf1, 0x1f, 0x08, 0xae, 0xce, 0x3d, 0xbf, - 0xfe, 0x41, 0xc5, 0xbf, 0x91, 0x0b, 0x47, 0x16, 0x75, 0xff, 0x71, 0x1b, - 0xc8, 0x6a, 0x2c, 0xeb, 0xff, 0x69, 0x07, 0x76, 0xfd, 0x34, 0x87, 0x56, - 0x1f, 0xa7, 0xcd, 0xef, 0xda, 0x5b, 0x81, 0xce, 0xa6, 0xa6, 0x10, 0xb8, - 0x60, 0xfc, 0x86, 0xff, 0xee, 0xad, 0xf3, 0xfe, 0x7d, 0xf5, 0xf7, 0x3a, - 0xff, 0xff, 0xf7, 0x21, 0x3e, 0xd0, 0x8f, 0xf5, 0xc8, 0x6f, 0x91, 0x79, - 0x75, 0xda, 0x75, 0xff, 0xb5, 0xe7, 0xe8, 0x21, 0x6e, 0x68, 0xea, 0x57, - 0x45, 0xb7, 0x1d, 0xef, 0xff, 0xec, 0xdf, 0x35, 0x03, 0xc4, 0x7f, 0xf0, - 0x30, 0xb3, 0xa9, 0xd3, 0x7c, 0x88, 0x7f, 0x09, 0x35, 0xfc, 0x21, 0x5a, - 0x71, 0xce, 0xbf, 0xff, 0x40, 0xfe, 0x23, 0x82, 0xff, 0xd3, 0x19, 0xc3, - 0xaf, 0xfd, 0xb4, 0x0e, 0xbf, 0xc4, 0x7d, 0x1d, 0x7b, 0xba, 0xd1, 0xe2, - 0x03, 0xbf, 0xfd, 0xd7, 0xe3, 0xf8, 0xce, 0xca, 0x22, 0x46, 0x88, 0x0e, - 0x63, 0x53, 0x50, 0x8c, 0xdf, 0x2c, 0xd5, 0xea, 0x68, 0x7f, 0x8c, 0x7e, - 0xf4, 0xe7, 0xe1, 0xd5, 0x89, 0xdb, 0x24, 0x6d, 0xde, 0x4a, 0xef, 0x72, - 0x15, 0xce, 0xbe, 0x7f, 0x67, 0xb0, 0xea, 0xf4, 0xf0, 0xbe, 0x3d, 0x7c, - 0x3f, 0xf4, 0x27, 0x5f, 0x96, 0xad, 0x2b, 0x4a, 0xd2, 0xb2, 0x75, 0xff, - 0xfc, 0xdc, 0xd2, 0x77, 0xa8, 0xbf, 0x3f, 0xe6, 0x31, 0xf3, 0xab, 0x11, - 0x76, 0x84, 0x50, 0x79, 0x7f, 0xff, 0xd0, 0xdc, 0x16, 0x5b, 0x9b, 0xb7, - 0xcb, 0xfb, 0x33, 0x0c, 0x30, 0x55, 0x3a, 0x6f, 0x3c, 0x86, 0xf0, 0x96, - 0xdf, 0xbd, 0x7f, 0xe2, 0xb9, 0xd7, 0xf9, 0xf3, 0xb2, 0x88, 0x91, 0xa2, - 0x09, 0xbf, 0xe7, 0xfe, 0x76, 0x51, 0x12, 0x34, 0x5f, 0x37, 0x87, 0x34, - 0x04, 0x40, 0x48, 0xf6, 0x85, 0x1b, 0xb3, 0xa1, 0x55, 0x7f, 0xf3, 0xf1, - 0x14, 0xce, 0xec, 0xb0, 0xee, 0x75, 0x21, 0xf7, 0xf0, 0xa6, 0xff, 0x07, - 0x93, 0xdc, 0x49, 0x70, 0xeb, 0xff, 0x6d, 0x1b, 0xcf, 0x67, 0xc6, 0x27, - 0x1d, 0x7f, 0xec, 0x03, 0xb5, 0xf9, 0x9e, 0xc1, 0xd7, 0x98, 0x61, 0x82, - 0xaf, 0xdc, 0xc9, 0x47, 0x4a, 0x98, 0xbf, 0xbf, 0xff, 0xcc, 0xf5, 0xe7, - 0x78, 0x52, 0x3c, 0x79, 0x67, 0x5e, 0x33, 0x7f, 0x9d, 0x5f, 0x45, 0x2f, - 0x93, 0x6a, 0xd9, 0x36, 0x85, 0xa1, 0x8c, 0x60, 0x17, 0xfe, 0x5b, 0xef, - 0xa1, 0xcd, 0xbc, 0xb4, 0xeb, 0xfc, 0xa7, 0x86, 0x5a, 0xfd, 0xd1, 0xd5, - 0xb1, 0xfc, 0x22, 0x0d, 0xfc, 0xaf, 0x8d, 0xe3, 0xf4, 0xeb, 0xfd, 0xf7, - 0x4e, 0x28, 0xfb, 0x9d, 0x7f, 0xfb, 0x71, 0xf1, 0x2e, 0x27, 0xbe, 0xbf, - 0x5a, 0x75, 0x3a, 0x2c, 0x10, 0xbf, 0xc9, 0x9d, 0xfa, 0x15, 0xf4, 0xd9, - 0xc7, 0x5f, 0xf8, 0x3a, 0x7c, 0x1f, 0xcf, 0xac, 0x48, 0xeb, 0xff, 0xfe, - 0xd6, 0xd8, 0xc0, 0xe0, 0x3a, 0x81, 0xd8, 0x1c, 0x71, 0xd8, 0xeb, 0xcc, - 0x30, 0xc1, 0x57, 0xfb, 0xcf, 0xae, 0x39, 0xbf, 0xca, 0x98, 0xbf, 0xbf, - 0xff, 0xa7, 0xef, 0x12, 0xe2, 0x00, 0x18, 0xc7, 0x8f, 0xeb, 0x36, 0x3a, - 0xb8, 0x8a, 0xb0, 0xa2, 0xd2, 0x26, 0xab, 0x11, 0x99, 0x53, 0x57, 0x57, - 0x00, 0x42, 0x91, 0xcf, 0x76, 0x15, 0xeb, 0x86, 0x97, 0x0c, 0x04, 0xb3, - 0xf1, 0xcc, 0x5f, 0xfb, 0x10, 0x76, 0x81, 0xfe, 0x2c, 0xeb, 0xff, 0x71, - 0x18, 0x07, 0x33, 0xf3, 0xd8, 0x75, 0xf6, 0x7d, 0x96, 0x9d, 0x7f, 0xf2, - 0xa1, 0x75, 0x5a, 0x81, 0xf3, 0xee, 0x8e, 0xae, 0x1f, 0x5c, 0x11, 0x5f, - 0xfb, 0x3e, 0xfd, 0xd7, 0x1c, 0x7e, 0x78, 0x82, 0x2f, 0xf3, 0xe7, 0x65, - 0x11, 0x23, 0x44, 0x11, 0x31, 0xe4, 0xdf, 0xd1, 0xce, 0xf5, 0x18, 0x3a, - 0xfe, 0x57, 0x03, 0x10, 0x2d, 0x3a, 0x84, 0xf7, 0x42, 0x5b, 0x5c, 0x4c, - 0xdf, 0xd6, 0xa1, 0x85, 0x65, 0xfd, 0xcc, 0xff, 0xd1, 0x67, 0x5f, 0xdf, - 0xf3, 0x9c, 0x8d, 0xce, 0xad, 0xcf, 0x6c, 0x4b, 0x2f, 0xff, 0x6b, 0x43, - 0x1f, 0x85, 0xf9, 0x7d, 0xb0, 0xea, 0x73, 0xec, 0x09, 0x15, 0xce, 0xa1, - 0xd7, 0xfe, 0xce, 0x3a, 0x7c, 0x73, 0x88, 0x75, 0xd0, 0xc7, 0x83, 0xd0, - 0xf8, 0xb5, 0x35, 0x14, 0x22, 0xe3, 0x7f, 0xdc, 0x7e, 0xfc, 0x5f, 0x37, - 0x3a, 0xff, 0xff, 0x93, 0x67, 0x6e, 0xbb, 0xd4, 0xdd, 0x96, 0xc7, 0x57, - 0x9b, 0x9d, 0x7d, 0xfe, 0x60, 0x81, 0x14, 0x1c, 0x37, 0xbf, 0xf4, 0xb8, - 0xf9, 0xd6, 0xe8, 0x2b, 0x3a, 0xfe, 0xf2, 0xbd, 0x31, 0x1b, 0x9d, 0x4e, - 0x8a, 0x8c, 0x39, 0xf9, 0xf5, 0xee, 0xe7, 0x0e, 0xbd, 0xa4, 0x59, 0xd6, - 0x7e, 0x9b, 0x6f, 0x8d, 0xdf, 0x23, 0x28, 0xc1, 0xd7, 0xff, 0x2e, 0x37, - 0xf3, 0xf4, 0xeb, 0x86, 0x7e, 0x3a, 0xff, 0xfc, 0x1d, 0x85, 0xf3, 0x93, - 0x3f, 0xf3, 0x81, 0xe9, 0xd7, 0xdf, 0xd7, 0x9d, 0x01, 0x18, 0x58, 0x45, - 0xe5, 0x2e, 0xfd, 0xa5, 0xe7, 0xf4, 0x75, 0xfa, 0x1a, 0x28, 0xe7, 0x5f, - 0xcf, 0x03, 0xfc, 0x13, 0xa9, 0xa9, 0xd3, 0xe4, 0x3a, 0x11, 0x2d, 0x64, - 0xe2, 0x49, 0x7f, 0x4b, 0x89, 0x3c, 0x8a, 0x1d, 0x7f, 0xf9, 0x3d, 0x7d, - 0x2d, 0xd3, 0xbd, 0x46, 0x0e, 0xbe, 0x57, 0xe6, 0x6c, 0x75, 0xfe, 0x70, - 0x67, 0xd3, 0x81, 0x3a, 0xcb, 0x73, 0xd6, 0x01, 0x2d, 0xff, 0xff, 0x97, - 0x03, 0xeb, 0x53, 0x41, 0x5f, 0x11, 0xff, 0xc0, 0xc2, 0xce, 0xbb, 0xc2, - 0xb9, 0xd7, 0xff, 0xe8, 0x4f, 0xa0, 0x30, 0x19, 0xf4, 0x5a, 0x74, 0xeb, - 0xdd, 0x8d, 0x74, 0xfb, 0x38, 0x37, 0x72, 0x7e, 0x13, 0x0a, 0x0c, 0x35, - 0xef, 0x43, 0x5c, 0xea, 0x02, 0xa4, 0xdc, 0x30, 0x48, 0x4f, 0xc4, 0x66, - 0x22, 0x67, 0x7f, 0x75, 0xf6, 0x41, 0xf9, 0xd7, 0xe1, 0x70, 0x63, 0x27, - 0x5f, 0x68, 0x3d, 0x50, 0xeb, 0xf3, 0xf3, 0xee, 0xd3, 0xaf, 0x80, 0x1f, - 0xe9, 0xcf, 0xbf, 0x72, 0x6f, 0x48, 0xef, 0xde, 0xe2, 0xdf, 0x87, 0x50, - 0x13, 0x0a, 0x48, 0x4d, 0x8a, 0x45, 0xee, 0xf9, 0xd1, 0xd7, 0x3a, 0xb6, - 0x3a, 0xff, 0xd0, 0x32, 0xce, 0xca, 0x22, 0x46, 0x88, 0x46, 0x9d, 0x10, - 0x3e, 0x8f, 0x04, 0x6e, 0xff, 0xf3, 0xe6, 0xfe, 0x7e, 0x82, 0x16, 0xe6, - 0x8e, 0xbf, 0xfb, 0xf0, 0x3b, 0x6e, 0xd1, 0x7c, 0xd1, 0xd7, 0xfe, 0xf3, - 0x9c, 0x85, 0xcc, 0xc3, 0x0c, 0x1d, 0x7f, 0xfe, 0xc9, 0x71, 0xc4, 0x02, - 0x9b, 0x60, 0xa2, 0x87, 0x5d, 0x11, 0xb2, 0x25, 0x9a, 0x89, 0x7f, 0xf7, - 0xf8, 0x93, 0xb9, 0x0d, 0xeb, 0xa8, 0x75, 0xfd, 0x8c, 0x60, 0x87, 0xd3, - 0xaf, 0xcd, 0xcf, 0xbf, 0xa7, 0x5c, 0xeb, 0xd8, 0xf5, 0x37, 0x2d, 0xbf, - 0xff, 0xfb, 0xd5, 0xc3, 0x79, 0x09, 0xf4, 0x06, 0x03, 0x3e, 0x8b, 0x4e, - 0x9d, 0x5a, 0x44, 0xf0, 0x4b, 0xef, 0xdb, 0x2d, 0xc0, 0xe7, 0x50, 0x15, - 0x69, 0xee, 0x94, 0xcc, 0x36, 0x78, 0x5d, 0xf8, 0xce, 0x3c, 0x91, 0xdf, - 0xf0, 0x1f, 0x5a, 0x7d, 0xb1, 0x83, 0xab, 0x11, 0x43, 0x0d, 0x17, 0x98, - 0x61, 0x82, 0xaf, 0xfb, 0x3d, 0x8e, 0xe4, 0xec, 0x01, 0x53, 0x17, 0xf7, - 0x30, 0xc1, 0x57, 0x98, 0x61, 0x82, 0xaf, 0xe8, 0xd8, 0x1c, 0x7d, 0x15, - 0x31, 0x7f, 0x42, 0x8b, 0xd6, 0x12, 0x67, 0x8d, 0xef, 0xd2, 0x40, 0x79, - 0x59, 0x53, 0x1b, 0x3b, 0xcc, 0x30, 0xc1, 0x57, 0xb4, 0xfd, 0x2a, 0x62, - 0xfe, 0xfa, 0x07, 0x7f, 0x9d, 0x6f, 0x51, 0x14, 0xbf, 0x59, 0x60, 0xae, - 0xfe, 0x00, 0xbb, 0x62, 0x47, 0x5f, 0xb4, 0x1d, 0xa7, 0x84, 0xeb, 0xf0, - 0x12, 0x73, 0x80, 0xeb, 0xec, 0x1c, 0x57, 0x3a, 0xba, 0x79, 0x4b, 0x28, - 0xa4, 0x44, 0xbf, 0x97, 0x5b, 0xff, 0xb9, 0x0d, 0x18, 0x51, 0x91, 0x46, - 0x4e, 0xbf, 0xb9, 0x93, 0xb3, 0xfa, 0x3a, 0xa4, 0x7e, 0x5f, 0x44, 0xae, - 0xa6, 0xf5, 0xc8, 0x61, 0x0c, 0x25, 0xa9, 0xd3, 0xeb, 0xc8, 0xec, 0x6f, - 0x6e, 0xad, 0xca, 0xc9, 0xd7, 0xff, 0xb1, 0x5e, 0x07, 0xdc, 0x93, 0xf1, - 0xd6, 0x75, 0xfd, 0x24, 0xd7, 0x11, 0x92, 0xaf, 0xf0, 0xe6, 0xed, 0xd2, - 0x28, 0x75, 0xf4, 0x47, 0x54, 0x3a, 0xbc, 0x1e, 0xa6, 0xc6, 0x77, 0xfd, - 0x99, 0x2f, 0x5f, 0x37, 0x69, 0xd7, 0xcf, 0x0b, 0x9c, 0x55, 0xfd, 0xcc, - 0x5a, 0xe1, 0xa7, 0x5e, 0x61, 0x86, 0x0a, 0xbf, 0xc3, 0xfe, 0x23, 0x8e, - 0xc5, 0x4c, 0x5f, 0xdf, 0x79, 0x7f, 0x71, 0xa8, 0x8c, 0xc4, 0xbb, 0x64, - 0x91, 0xd2, 0xb8, 0x57, 0x5f, 0xe7, 0xf3, 0xde, 0xa7, 0xf4, 0x75, 0x3a, - 0xa9, 0xb6, 0x94, 0xee, 0x94, 0x90, 0x81, 0x64, 0x97, 0x91, 0x90, 0x89, - 0x6d, 0xfb, 0xdc, 0x4e, 0x28, 0x75, 0xff, 0xf6, 0x49, 0xc6, 0x3f, 0xa0, - 0x06, 0x3a, 0xd3, 0xab, 0x73, 0xf5, 0x59, 0x45, 0xe9, 0x3e, 0x8e, 0xbf, - 0xfb, 0xcb, 0x73, 0x91, 0xc4, 0xef, 0x5c, 0xea, 0xc3, 0xdf, 0xf4, 0x6e, - 0xfc, 0xff, 0xd4, 0xec, 0x3a, 0xfc, 0x1e, 0xa9, 0xc4, 0x3a, 0x9d, 0x1e, - 0x83, 0x08, 0x2f, 0x91, 0x4f, 0x14, 0x5f, 0xff, 0x24, 0xec, 0x10, 0x0c, - 0x31, 0x83, 0x0a, 0x1d, 0x7f, 0xff, 0xc0, 0xe2, 0x31, 0x8a, 0x91, 0x71, - 0xfd, 0x05, 0xb9, 0xbf, 0xce, 0xac, 0x45, 0xbc, 0x27, 0x5f, 0xb6, 0xf0, - 0x17, 0x64, 0xeb, 0x9a, 0xd3, 0xaa, 0x0f, 0x07, 0x45, 0x74, 0xee, 0x99, - 0x2f, 0x68, 0xec, 0x9b, 0x1f, 0x48, 0x23, 0xf2, 0xc9, 0xed, 0xc5, 0x21, - 0x11, 0x23, 0xb4, 0x8f, 0x8d, 0x98, 0xe7, 0xbb, 0x1b, 0x52, 0xe5, 0x05, - 0xf2, 0x54, 0xd4, 0x46, 0xbb, 0xec, 0x2d, 0x46, 0x5d, 0x26, 0xa5, 0xe0, - 0x7e, 0x56, 0x18, 0x63, 0xd9, 0x62, 0x1f, 0x5e, 0x58, 0xaf, 0x4e, 0x71, - 0x3a, 0xff, 0xfb, 0x06, 0x6f, 0xa8, 0x9b, 0xeb, 0x99, 0xec, 0x1d, 0x4d, - 0x3e, 0xd0, 0x0e, 0x5f, 0xe8, 0x19, 0x67, 0xf8, 0x87, 0x56, 0xe7, 0xa4, - 0xb2, 0x2b, 0x95, 0xbd, 0x5b, 0x1d, 0x79, 0xc7, 0x63, 0xaf, 0x93, 0x88, - 0xb3, 0xad, 0xc4, 0x37, 0x6c, 0x8d, 0xdf, 0xf8, 0x5f, 0xfc, 0x8f, 0x63, - 0x7d, 0x1d, 0x79, 0x90, 0xf4, 0xeb, 0xff, 0x42, 0x77, 0x37, 0x99, 0x86, - 0x18, 0x3a, 0xa0, 0xf7, 0xf4, 0x3b, 0x7f, 0xfc, 0x2e, 0xdf, 0x1e, 0x7e, - 0x82, 0x16, 0xe6, 0x8e, 0xac, 0x4c, 0xda, 0x44, 0xfc, 0x84, 0xef, 0xa4, - 0x37, 0xf9, 0xc5, 0xa3, 0x99, 0xe9, 0xd7, 0xf6, 0x77, 0x42, 0xfb, 0x1d, - 0x7f, 0x47, 0xf9, 0x03, 0xe9, 0xd7, 0xfe, 0x8f, 0xe3, 0x30, 0xe2, 0xec, - 0x9d, 0x64, 0xe9, 0xf4, 0x70, 0xb2, 0x9a, 0x8b, 0xb9, 0x42, 0x52, 0xff, - 0xfb, 0x3e, 0xe3, 0x2c, 0xff, 0x13, 0xbe, 0xc8, 0xeb, 0xfc, 0xeb, 0xd6, - 0xa0, 0x76, 0x3a, 0xfd, 0x1a, 0xc1, 0xf9, 0xd7, 0xbf, 0x0a, 0xe7, 0x5f, - 0xef, 0xf1, 0x26, 0xf6, 0x10, 0xea, 0x02, 0x3d, 0xb8, 0x9c, 0x26, 0x5f, - 0x25, 0x08, 0xf5, 0xf7, 0x12, 0x1a, 0x75, 0xe0, 0x43, 0x4e, 0xb8, 0x3e, - 0xb9, 0xbb, 0xc2, 0x0b, 0xfe, 0x96, 0x7d, 0xe7, 0x20, 0xfa, 0x75, 0xff, - 0xfc, 0x17, 0xfe, 0xb0, 0x7c, 0x75, 0xd0, 0x03, 0x0d, 0x3a, 0xfd, 0x2e, - 0x6f, 0x0a, 0xe7, 0x52, 0x22, 0xf4, 0x4e, 0x42, 0xb3, 0x7f, 0xff, 0x0e, - 0x68, 0x3e, 0x33, 0x90, 0x38, 0xcb, 0x5f, 0x73, 0xaf, 0xfd, 0x9a, 0x0e, - 0x76, 0x51, 0x12, 0x34, 0x40, 0xd7, 0xdf, 0xe4, 0x37, 0xc2, 0x29, 0x05, - 0x6e, 0xff, 0x87, 0xdf, 0xa6, 0xcb, 0x79, 0x1d, 0x7e, 0x04, 0xf9, 0x00, - 0x9f, 0x0e, 0xa7, 0x4d, 0xdf, 0x21, 0xa4, 0x87, 0x70, 0x73, 0x7f, 0xb3, - 0x7f, 0x83, 0x31, 0x43, 0xaf, 0xec, 0xfb, 0x8a, 0x7a, 0x75, 0xff, 0xa3, - 0xb8, 0x3e, 0xeb, 0xfa, 0xdc, 0xeb, 0xff, 0xff, 0xfb, 0x3f, 0xc8, 0x15, - 0x3c, 0x6b, 0xb1, 0x1f, 0x9d, 0x80, 0xf1, 0x8b, 0x81, 0xdd, 0xa7, 0x88, - 0x2e, 0xff, 0xd1, 0x0a, 0x4a, 0x01, 0xe1, 0x46, 0x0f, 0x10, 0x5d, 0xff, - 0xdc, 0x4e, 0x23, 0x8f, 0xfc, 0x28, 0xc1, 0xe2, 0x0b, 0xbf, 0xce, 0x83, - 0xff, 0x0a, 0x30, 0x78, 0x82, 0xef, 0xe5, 0xe0, 0x3c, 0x28, 0xc1, 0xe2, - 0x0b, 0xbf, 0xff, 0xe8, 0x11, 0x45, 0xf8, 0xd4, 0xb8, 0x9d, 0x45, 0x36, - 0xc6, 0x0f, 0x10, 0x5d, 0xdb, 0xf8, 0x02, 0x72, 0xf2, 0x4f, 0xea, 0x9c, - 0x21, 0x09, 0xf5, 0x3a, 0xac, 0x8e, 0x1f, 0x8c, 0xa3, 0x1b, 0xfc, 0x8e, - 0xa6, 0xbf, 0xad, 0xce, 0xbe, 0x8e, 0xfb, 0x07, 0x5f, 0xfd, 0xc4, 0xe2, - 0x38, 0xff, 0xc2, 0x8c, 0x1e, 0x20, 0xbb, 0xfe, 0x67, 0x52, 0x4d, 0xbc, - 0x28, 0xc1, 0xe2, 0x0b, 0xbf, 0x7f, 0x4e, 0xbf, 0x12, 0x44, 0xff, 0x95, - 0x3b, 0xff, 0xde, 0x25, 0xc4, 0x93, 0xff, 0x5e, 0x14, 0x60, 0xf1, 0x05, - 0xdf, 0xff, 0xfc, 0x22, 0x8b, 0xf0, 0x1c, 0xf1, 0xa9, 0x71, 0x3a, 0x8a, - 0x6d, 0x8c, 0x1e, 0x20, 0xba, 0xc4, 0xc9, 0x37, 0x44, 0x85, 0xdb, 0xfe, - 0xe2, 0x75, 0x14, 0xdb, 0x18, 0x3c, 0x41, 0x77, 0xff, 0xd1, 0x1b, 0xb7, - 0x5c, 0x40, 0x01, 0xfa, 0xe5, 0x5f, 0xfb, 0x1a, 0xd0, 0xeb, 0xa3, 0xb4, - 0xf1, 0xe2, 0x0b, 0xa9, 0x23, 0x93, 0xa8, 0xfa, 0x4e, 0xbf, 0xf4, 0x93, - 0xbf, 0x8f, 0x75, 0xe1, 0x83, 0xc4, 0x17, 0x7f, 0x71, 0x39, 0xc4, 0xf4, - 0xd0, 0x05, 0xdf, 0xb3, 0xdf, 0x0a, 0x30, 0x78, 0x82, 0xee, 0xcf, 0xc8, - 0xfc, 0xf8, 0x75, 0x5b, 0xa3, 0xbf, 0x50, 0xc2, 0xbf, 0x97, 0x80, 0xf0, - 0xa3, 0x07, 0x88, 0x2e, 0xff, 0xd2, 0xe2, 0x75, 0x14, 0xdb, 0x18, 0x3c, - 0x41, 0x77, 0x67, 0x88, 0x44, 0x5e, 0x8f, 0xaf, 0xf0, 0x51, 0x70, 0x3b, - 0xb4, 0xf1, 0x05, 0xdf, 0xfb, 0x12, 0x76, 0x0e, 0x02, 0x1a, 0x78, 0x82, - 0xd6, 0x6f, 0xe8, 0x0b, 0xbf, 0xbd, 0x37, 0xf4, 0xd0, 0x63, 0xe4, 0xd4, - 0x62, 0x9f, 0x8c, 0x7c, 0x30, 0xb4, 0x61, 0xba, 0xef, 0x5c, 0xd1, 0x05, - 0xcc, 0x88, 0xcb, 0xa2, 0x47, 0x5b, 0x5e, 0x9e, 0x5f, 0xcd, 0xae, 0x6a, - 0xa3, 0xaf, 0x3b, 0x55, 0x1d, 0x4e, 0x6d, 0x44, 0x62, 0xb6, 0x65, 0x3b, - 0x80, 0xcf, 0xda, 0x4e, 0x38, 0xaf, 0x5f, 0xfb, 0x1b, 0xc8, 0x6a, 0xa5, - 0x41, 0xd8, 0xeb, 0xfa, 0x1a, 0xf3, 0xa3, 0x87, 0x5f, 0x6f, 0xa7, 0xdc, - 0xeb, 0xcb, 0x76, 0x9d, 0x7e, 0xc0, 0x70, 0x2c, 0x1d, 0x5e, 0x0f, 0x9a, - 0x08, 0xc4, 0x6e, 0xf0, 0x23, 0xe7, 0x57, 0x4f, 0x2a, 0x0b, 0xef, 0x24, - 0xf6, 0x1d, 0x7a, 0x3b, 0xe9, 0xd6, 0xdd, 0xcd, 0xcf, 0xc7, 0x6f, 0x98, - 0xce, 0x41, 0xd7, 0xca, 0x75, 0x18, 0x3a, 0xfd, 0xb4, 0x71, 0xd5, 0xce, - 0xa5, 0x64, 0xf3, 0x70, 0x8e, 0x9d, 0x3f, 0x24, 0x86, 0xec, 0x2d, 0x7a, - 0x4e, 0x2d, 0xd7, 0xff, 0xd8, 0x22, 0xfb, 0x2f, 0x89, 0xde, 0xc3, 0x4e, - 0xbd, 0x1d, 0xd8, 0xeb, 0xbd, 0x73, 0xaf, 0x91, 0xd7, 0x87, 0x51, 0xd7, - 0xf4, 0x29, 0xf7, 0xef, 0xa7, 0x50, 0x0d, 0xc0, 0x85, 0x5f, 0xff, 0xe7, - 0x40, 0x0b, 0x86, 0x5f, 0xc9, 0x01, 0xe5, 0xe5, 0x67, 0x5d, 0xeb, 0x9d, - 0x73, 0xa8, 0x75, 0xff, 0x67, 0xf4, 0xeb, 0xf3, 0x8c, 0x9d, 0x7f, 0xb5, - 0x9c, 0x4d, 0x07, 0x63, 0xae, 0x61, 0x82, 0xaf, 0xf8, 0x72, 0x74, 0x37, - 0x48, 0x03, 0xaa, 0x49, 0xf9, 0x20, 0xe7, 0x45, 0x96, 0xaf, 0xc2, 0x0f, - 0x58, 0x27, 0xe1, 0x61, 0x16, 0xd1, 0xd3, 0x06, 0x7e, 0x46, 0x2f, 0x30, - 0xc3, 0x05, 0x59, 0x65, 0x4c, 0x5f, 0xdf, 0xa1, 0x98, 0x8e, 0x95, 0x32, - 0x37, 0xfc, 0xc2, 0xfe, 0xfe, 0xfb, 0xe7, 0x33, 0x63, 0xae, 0xc5, 0x9d, - 0x5b, 0x9e, 0x0e, 0x8b, 0x29, 0xdb, 0x83, 0x96, 0x91, 0xe4, 0x72, 0x8a, - 0x21, 0xef, 0x0e, 0xb4, 0x8c, 0x7b, 0xb0, 0x84, 0xe4, 0xa6, 0x08, 0xa5, - 0x5b, 0x0a, 0x5e, 0xa5, 0x1a, 0xfd, 0x34, 0x32, 0xc7, 0xa7, 0x42, 0x3a, - 0xf4, 0x4b, 0x0e, 0xbb, 0x18, 0x3a, 0xe7, 0xf9, 0xd5, 0xb1, 0xab, 0x90, - 0xb5, 0x96, 0x75, 0x61, 0xb2, 0xf9, 0x15, 0xfc, 0xb7, 0xdb, 0xf9, 0x23, - 0xaf, 0xb1, 0x79, 0xf3, 0xaf, 0x7e, 0x14, 0x3a, 0xff, 0xff, 0xe9, 0x43, - 0x21, 0x68, 0x65, 0xe3, 0x89, 0xff, 0xbe, 0xef, 0xb3, 0xe8, 0xeb, 0xff, - 0xfe, 0x57, 0x18, 0x89, 0xce, 0xde, 0x3f, 0x76, 0x7f, 0xea, 0x1a, 0x75, - 0xe4, 0xdd, 0x93, 0xaf, 0xd9, 0x9b, 0x07, 0x47, 0x5f, 0x74, 0x53, 0xd3, - 0xaf, 0xfc, 0x1d, 0x83, 0x37, 0x12, 0x51, 0xd3, 0xa9, 0x0f, 0x87, 0x84, - 0x37, 0xfd, 0xc8, 0xd7, 0x13, 0x68, 0x13, 0xaf, 0xa3, 0x6f, 0x2d, 0x3a, - 0xa7, 0xf5, 0x60, 0x0e, 0xef, 0xb1, 0x06, 0xe5, 0xa8, 0x41, 0xd1, 0xc8, - 0x76, 0xf5, 0xa7, 0x43, 0xbf, 0x84, 0x47, 0x92, 0x15, 0x46, 0xf7, 0xf0, - 0x84, 0x0b, 0x86, 0x9d, 0x7f, 0xf9, 0xa2, 0xfe, 0x16, 0x2e, 0xa7, 0xd3, - 0x63, 0xaf, 0xd0, 0xbc, 0xe2, 0xce, 0xad, 0xcf, 0xc7, 0xe9, 0x77, 0xbf, - 0xd7, 0x3a, 0xff, 0x6b, 0xf3, 0xb0, 0x70, 0x07, 0x53, 0xa6, 0x1c, 0x90, - 0x9d, 0x59, 0x1c, 0x0d, 0xde, 0x8f, 0x1e, 0x4e, 0xbe, 0x5a, 0xdd, 0x67, - 0x5f, 0xff, 0x0b, 0x7c, 0x60, 0x13, 0x5b, 0xfc, 0x31, 0xa3, 0xaf, 0xca, - 0x6b, 0x48, 0xc9, 0xd7, 0xff, 0x46, 0xc2, 0xfb, 0xa0, 0x05, 0xf6, 0x3a, - 0xba, 0x7d, 0x82, 0x53, 0x7e, 0xf1, 0xc7, 0xeb, 0x4e, 0xaf, 0x09, 0xa3, - 0xb8, 0xfe, 0x10, 0xc4, 0x2f, 0x58, 0x21, 0xbc, 0xbd, 0x39, 0xd7, 0xf6, - 0xcc, 0xb6, 0x7f, 0xee, 0xc7, 0x5f, 0x2f, 0x23, 0x87, 0x5c, 0xdd, 0x8e, - 0xbf, 0x73, 0x11, 0xba, 0x3a, 0xff, 0xfb, 0x8f, 0xe6, 0x6f, 0x8c, 0x7b, - 0xad, 0x3f, 0xa5, 0x5f, 0xbb, 0x28, 0x89, 0x1e, 0x20, 0x4b, 0xda, 0x7d, - 0xce, 0xb7, 0xb8, 0x79, 0xfb, 0x99, 0xde, 0xfa, 0x6c, 0x75, 0xed, 0xa0, - 0x4e, 0xa6, 0xa6, 0x50, 0x02, 0x6e, 0xc2, 0x89, 0x65, 0x3f, 0x1c, 0xbf, - 0x86, 0x50, 0xa7, 0x10, 0xeb, 0x95, 0x34, 0xeb, 0xef, 0xed, 0x02, 0x75, - 0xe1, 0x85, 0x0e, 0xbe, 0xdf, 0x51, 0xf3, 0xaf, 0xe5, 0xfd, 0x00, 0x17, - 0x3a, 0xf2, 0xff, 0x23, 0xad, 0xf7, 0x3c, 0x8c, 0x2c, 0xad, 0x91, 0xc9, - 0x83, 0x12, 0x21, 0xe0, 0xd8, 0xb5, 0x5d, 0xd0, 0x9d, 0x7f, 0x86, 0x18, - 0xd6, 0x9f, 0xd3, 0xaf, 0x4f, 0x42, 0x87, 0x5f, 0xf3, 0xad, 0xb9, 0xb6, - 0x06, 0x7e, 0x3a, 0xb0, 0xf7, 0x10, 0x7e, 0xf3, 0x0c, 0x30, 0x7a, 0xbe, - 0xaf, 0x40, 0x80, 0xb5, 0x7d, 0x26, 0x35, 0x97, 0xec, 0x68, 0x5d, 0x43, - 0xa9, 0xd3, 0x51, 0x00, 0xb7, 0x61, 0x1f, 0xea, 0x67, 0xce, 0x6f, 0xff, - 0xd8, 0x28, 0xa4, 0xda, 0xff, 0x03, 0x0d, 0x6b, 0x9d, 0x5b, 0x22, 0x95, - 0x45, 0x0b, 0xec, 0x04, 0x34, 0xeb, 0xf4, 0x08, 0xa2, 0xce, 0xbf, 0xee, - 0x27, 0x71, 0x16, 0xea, 0xe7, 0x5f, 0x91, 0x70, 0x38, 0x75, 0x78, 0x5e, - 0x15, 0x56, 0x86, 0xdc, 0xd9, 0xa4, 0x19, 0x19, 0xfa, 0x8a, 0x09, 0x18, - 0x84, 0x4a, 0x3f, 0xf4, 0x94, 0x48, 0x02, 0x49, 0x3c, 0x73, 0x7e, 0x4f, - 0xbf, 0xf4, 0x55, 0xf4, 0x9f, 0xfa, 0x2a, 0xe6, 0x18, 0x2a, 0x9a, 0x7b, - 0xf8, 0x4c, 0xc1, 0x0d, 0xd8, 0xc1, 0x53, 0x1a, 0xfb, 0xff, 0xf6, 0x7d, - 0xe5, 0x98, 0x3f, 0xe2, 0x38, 0xec, 0x75, 0x7a, 0x7f, 0x0c, 0x13, 0xdf, - 0xff, 0xe7, 0x9c, 0x83, 0xef, 0x8f, 0xeb, 0x25, 0xc8, 0x1f, 0xe8, 0xeb, - 0xf3, 0x78, 0x17, 0xe9, 0xd7, 0xff, 0x42, 0xfa, 0xf3, 0x92, 0x70, 0x87, - 0x47, 0x56, 0xe7, 0xdb, 0xc2, 0x7b, 0xf6, 0x05, 0x6f, 0xa3, 0xa8, 0xeb, - 0xd9, 0x8c, 0xf4, 0xd8, 0x68, 0x9a, 0x99, 0x44, 0x2f, 0x54, 0xef, 0x36, - 0x3a, 0x75, 0xf9, 0xb9, 0xfc, 0x01, 0x57, 0xce, 0x22, 0xe7, 0x59, 0x19, - 0x3d, 0xff, 0x8d, 0xf9, 0x26, 0xbf, 0xe1, 0xce, 0x67, 0x8e, 0x66, 0xc7, - 0x5f, 0xc1, 0x9f, 0x93, 0xbd, 0xc3, 0xaf, 0xbe, 0xa6, 0x70, 0xeb, 0xfb, - 0xd0, 0xeb, 0xc2, 0x7a, 0x75, 0xde, 0xb9, 0xd7, 0x7a, 0xe7, 0x5f, 0x82, - 0xdc, 0x19, 0x90, 0xd6, 0x7a, 0x2d, 0x4e, 0x8b, 0xdf, 0x48, 0x85, 0x76, - 0xff, 0xfb, 0x06, 0x37, 0xd2, 0x8a, 0x47, 0x89, 0x2f, 0xd3, 0xaf, 0xfe, - 0xff, 0x31, 0x7e, 0x5f, 0xdc, 0xdf, 0xe7, 0x5f, 0xed, 0xe4, 0x9d, 0xf2, - 0xe0, 0x3a, 0xfb, 0xd5, 0xc3, 0x7c, 0x23, 0x43, 0x4a, 0x9f, 0x47, 0xbf, - 0xbd, 0x5f, 0x9d, 0x79, 0xd8, 0xeb, 0xb3, 0x73, 0xab, 0x73, 0xca, 0x9e, - 0x34, 0xbe, 0xf7, 0xa9, 0xd3, 0xa9, 0xd1, 0xb9, 0x10, 0x94, 0x60, 0x9a, - 0xfb, 0x41, 0xdf, 0xe7, 0x5e, 0xee, 0x30, 0x75, 0xff, 0x99, 0x7d, 0xb5, - 0xdc, 0x93, 0xec, 0x75, 0xfe, 0x5e, 0x2f, 0x00, 0x8c, 0x1d, 0x7f, 0x0e, - 0x33, 0xc4, 0xf9, 0xd7, 0xd9, 0x9c, 0xd1, 0xd5, 0x88, 0xbe, 0x84, 0x0f, - 0x99, 0x2a, 0x2c, 0xbc, 0xc3, 0x0c, 0x15, 0x7e, 0xc5, 0x04, 0x3a, 0x2a, - 0x62, 0xfe, 0xfd, 0x93, 0x30, 0xc3, 0x07, 0x53, 0x9f, 0x17, 0xcd, 0xef, - 0xfc, 0x39, 0xa9, 0x71, 0x24, 0xe2, 0x75, 0xff, 0xfe, 0x51, 0x88, 0xea, - 0x93, 0x6b, 0x1a, 0x21, 0x8d, 0x60, 0x9d, 0x58, 0x89, 0xd4, 0x3b, 0xbe, - 0x62, 0x05, 0xa7, 0x5f, 0xf7, 0xdf, 0x7f, 0x63, 0x9c, 0x43, 0xad, 0xc3, - 0xab, 0x0f, 0x26, 0x47, 0x37, 0x98, 0x61, 0x82, 0xaf, 0xe4, 0x85, 0x38, - 0x9f, 0x2a, 0x62, 0xfe, 0xfa, 0x38, 0xe0, 0x3a, 0xfd, 0x9e, 0xe6, 0x32, - 0x75, 0xb5, 0xe1, 0x18, 0x7d, 0x40, 0xe1, 0xe0, 0x90, 0x5c, 0x16, 0x81, - 0x37, 0x1c, 0x8c, 0xb6, 0xfd, 0x3f, 0x71, 0xf6, 0x09, 0xd6, 0x4e, 0x27, - 0xe8, 0x31, 0xc9, 0x04, 0xd6, 0xfa, 0x3a, 0x9c, 0x3a, 0xff, 0x38, 0xb4, - 0x51, 0xf7, 0x3a, 0x9d, 0x94, 0xc2, 0xd2, 0x4c, 0x8d, 0x55, 0x48, 0x41, - 0xc8, 0xdd, 0x0e, 0x7b, 0x0e, 0xee, 0x47, 0xb7, 0x06, 0x9e, 0x91, 0x8c, - 0x36, 0xb5, 0x0b, 0xef, 0xca, 0xb2, 0x9e, 0x3b, 0x54, 0x41, 0x72, 0xb2, - 0x87, 0x5f, 0xf9, 0xd9, 0xfa, 0xad, 0x3b, 0x21, 0xe9, 0xd7, 0xf3, 0xaf, - 0xbd, 0x8f, 0x9d, 0x7f, 0xfa, 0x4c, 0xc4, 0xb8, 0xed, 0xf8, 0xe2, 0xce, - 0xbf, 0xfe, 0x45, 0xee, 0xdd, 0x78, 0xc1, 0x1c, 0x4f, 0x4e, 0xbc, 0x9c, - 0x09, 0xd4, 0xad, 0x26, 0x78, 0xd1, 0xae, 0x21, 0x41, 0x67, 0xd2, 0x67, - 0x28, 0x5a, 0x69, 0xf6, 0x31, 0x7d, 0x69, 0xf2, 0x30, 0x75, 0x6c, 0xb4, - 0xad, 0xf0, 0xd4, 0x56, 0x25, 0x0f, 0x48, 0xfb, 0xda, 0x5f, 0x83, 0x67, - 0x62, 0x41, 0x3d, 0x4d, 0x96, 0xb5, 0x6d, 0x49, 0x4f, 0x12, 0x9f, 0x56, - 0xde, 0x7a, 0x49, 0x27, 0xa6, 0x19, 0xa5, 0x0a, 0xf6, 0x95, 0x36, 0xb9, - 0xcd, 0xfe, 0x56, 0x34, 0x51, 0x5b, 0x9c, 0xfb, 0x3d, 0xd5, 0x3f, 0x43, - 0x14, 0x69, 0xe5, 0x7a, 0xb4, 0xfd, 0x5f, 0xae, 0x9d, 0xc3, 0x2f, 0xf2, - 0x74, 0x78, 0x6c, 0x47, 0x0f, 0x3d, 0x3c, 0xcb, 0xe6, 0x98, 0x52, 0xaa, - 0x51, 0xad, 0x4d, 0x18, 0xd9, 0xab, 0x73, 0x18, 0x91, 0xbf, 0x4d, 0xea, - 0xf3, 0xe7, 0x5f, 0xe9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0xe3, 0xbf, 0xd3, - 0x67, 0x65, 0x11, 0x23, 0x45, 0xd7, 0x7f, 0xf4, 0xd0, 0xd9, 0xb3, 0xb2, - 0x88, 0x91, 0xa2, 0x51, 0xa7, 0x8c, 0x7f, 0x25, 0xb0, 0x86, 0x01, 0x72, - 0x90, 0x8f, 0x91, 0x42, 0x46, 0x80, 0xae, 0xbf, 0x19, 0x8d, 0xc6, 0x7a, - 0x77, 0xa2, 0x9f, 0x9f, 0xaa, 0x3f, 0xbf, 0xfd, 0x32, 0xe1, 0xb3, 0x67, - 0x65, 0x11, 0x23, 0x44, 0xb5, 0x7e, 0xec, 0xa2, 0x24, 0x68, 0x8d, 0xef, - 0xfd, 0x0d, 0x9b, 0x3b, 0x28, 0x89, 0x1a, 0x25, 0xfb, 0xf9, 0xff, 0xe7, - 0x91, 0xf3, 0xad, 0x36, 0x22, 0xad, 0x66, 0x7c, 0x4a, 0xbf, 0xd3, 0x67, - 0x65, 0x11, 0x23, 0x45, 0x57, 0x72, 0x2a, 0x3a, 0xf9, 0x17, 0x13, 0x8e, - 0xa5, 0x0d, 0xcf, 0xc5, 0xef, 0x0a, 0xa6, 0x0e, 0xbf, 0xa3, 0x8c, 0x8b, - 0x80, 0xeb, 0xff, 0xbf, 0xc7, 0xd0, 0xc0, 0x67, 0xe4, 0xe9, 0xd7, 0x9d, - 0xb8, 0x75, 0x01, 0x11, 0xbb, 0x96, 0x32, 0x8f, 0x7f, 0xca, 0x60, 0xe6, - 0xff, 0x85, 0x9d, 0x70, 0x10, 0xeb, 0xfb, 0x3b, 0x28, 0x89, 0x1a, 0x24, - 0x0a, 0xf0, 0x79, 0xb3, 0x0a, 0xdf, 0xb5, 0x03, 0x1b, 0x9d, 0x4d, 0x3c, - 0xbd, 0xc9, 0x6f, 0xf3, 0x5f, 0xbb, 0x3f, 0x76, 0x3a, 0xff, 0x77, 0x65, - 0xb8, 0xb7, 0x47, 0x53, 0x9f, 0x3e, 0x1a, 0x5f, 0xfe, 0xc6, 0x79, 0x0b, - 0xff, 0x1f, 0xe1, 0x59, 0xd5, 0xb2, 0xac, 0x30, 0x11, 0x64, 0x2a, 0xd4, - 0x32, 0x88, 0x68, 0x0c, 0x22, 0xbc, 0x90, 0x5f, 0xfc, 0x39, 0xb4, 0xd3, - 0xce, 0x23, 0x9f, 0x3a, 0xa6, 0x45, 0xdf, 0x5d, 0xaf, 0xf4, 0xd9, 0xd9, - 0x44, 0x48, 0xd1, 0x64, 0x5f, 0xe9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0xd7, - 0xbf, 0xfd, 0x9e, 0x5f, 0x69, 0xb1, 0x9f, 0x81, 0xc4, 0xeb, 0xfd, 0x36, - 0x76, 0x51, 0x12, 0x34, 0x5c, 0x97, 0xee, 0xca, 0x22, 0x46, 0x8b, 0xb2, - 0xff, 0xd0, 0xd9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x8e, 0xb4, 0xd8, 0x7f, - 0xab, 0x33, 0xbe, 0x17, 0x6a, 0xce, 0xb3, 0x4e, 0xbf, 0x76, 0x51, 0x12, - 0x34, 0x52, 0xb7, 0xfd, 0x2e, 0x23, 0x3c, 0x7d, 0xb0, 0xeb, 0xff, 0xdc, - 0x7d, 0x9f, 0x89, 0x3a, 0x01, 0xc4, 0x3a, 0x63, 0x73, 0x73, 0x66, 0xc4, - 0x63, 0xb2, 0xd9, 0x5b, 0xa6, 0x0f, 0x10, 0xd7, 0xb4, 0xc0, 0x4d, 0x41, - 0x71, 0x93, 0xd6, 0xcc, 0x88, 0x16, 0xc6, 0x05, 0xb9, 0xb2, 0x4b, 0xf6, - 0x59, 0x27, 0xa7, 0xe2, 0x7f, 0xa4, 0xcf, 0xc2, 0xf2, 0x74, 0x6f, 0x17, - 0xfc, 0xd9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x38, 0xbf, 0xe4, 0x9b, 0x3b, - 0x28, 0x89, 0x1a, 0x2b, 0x5b, 0x4d, 0x08, 0x89, 0xfa, 0x2d, 0xff, 0xe9, - 0x97, 0x0d, 0x9b, 0x3b, 0x28, 0x89, 0x1a, 0x25, 0xbb, 0xb3, 0x73, 0xaf, - 0xf0, 0x31, 0x6b, 0x74, 0xd1, 0xd5, 0xb9, 0xe3, 0xa0, 0xb5, 0xee, 0x01, - 0xa7, 0x5f, 0xf6, 0x6e, 0x39, 0xef, 0xb0, 0xd3, 0xae, 0x5c, 0x8e, 0xa7, - 0x3c, 0xf6, 0x9c, 0xdf, 0xff, 0xdc, 0x8d, 0xfd, 0x07, 0x21, 0xb9, 0xa1, - 0x0c, 0x79, 0x3a, 0xfe, 0x4e, 0x8a, 0x7f, 0x47, 0x5f, 0xbb, 0x03, 0x8e, - 0x75, 0x1a, 0x21, 0xbe, 0x1e, 0x7c, 0x15, 0xdf, 0xe6, 0xa0, 0x83, 0x10, - 0x07, 0x5f, 0x63, 0x2d, 0xc3, 0xaf, 0xfd, 0x0d, 0x9b, 0x3b, 0x28, 0x89, - 0x1a, 0x26, 0x0b, 0xf7, 0xba, 0x81, 0xf4, 0xeb, 0xff, 0xbf, 0x3c, 0xfb, - 0x7c, 0x5c, 0x3f, 0xd1, 0xd7, 0xdb, 0xc9, 0x14, 0x3a, 0xb0, 0xfa, 0xbe, - 0x8f, 0x7f, 0xb4, 0x9c, 0x45, 0xe2, 0x87, 0x5f, 0xfe, 0x8d, 0xb8, 0x8e, - 0x38, 0xca, 0x75, 0x0e, 0xaf, 0x9f, 0xcb, 0x06, 0x57, 0x4b, 0x0e, 0xb8, - 0x3e, 0x95, 0x48, 0x6b, 0x3a, 0x2b, 0x7f, 0xb0, 0x03, 0x9f, 0xe6, 0x1d, - 0x7f, 0x6d, 0xe6, 0x7a, 0x07, 0xd3, 0xaf, 0xec, 0xff, 0xdf, 0xba, 0x3a, - 0xfe, 0x81, 0xf7, 0x6f, 0x7e, 0x75, 0x3a, 0x23, 0x84, 0xce, 0x78, 0xb2, - 0xd3, 0x3a, 0xe5, 0x9e, 0xc4, 0x40, 0x6b, 0xc2, 0x19, 0x42, 0xb3, 0x73, - 0x4e, 0x98, 0x2c, 0x86, 0x12, 0x86, 0x12, 0x5a, 0x84, 0xd7, 0xd3, 0xe7, - 0x10, 0x79, 0x85, 0xf5, 0xe5, 0x87, 0xa5, 0x5f, 0xfa, 0x1b, 0x36, 0x76, - 0x51, 0x12, 0x34, 0x4c, 0x77, 0xcf, 0xd7, 0x54, 0x75, 0xa6, 0x44, 0x44, - 0x2c, 0x73, 0x89, 0x57, 0xe4, 0x7d, 0x9f, 0xa7, 0x5d, 0x1a, 0x3a, 0xfb, - 0xc7, 0xf3, 0x87, 0x59, 0xf8, 0x6e, 0x34, 0x2b, 0x79, 0xc7, 0x63, 0xaf, - 0xff, 0xff, 0x9b, 0xae, 0x60, 0x58, 0xd7, 0x32, 0x59, 0xaf, 0x19, 0xbb, - 0x74, 0x82, 0x87, 0x5f, 0x4a, 0x22, 0x46, 0x8a, 0xc6, 0xff, 0xd3, 0xd9, - 0xf1, 0xc0, 0xb8, 0xfc, 0xea, 0x51, 0x32, 0xb9, 0x13, 0x6e, 0x37, 0xd7, - 0xff, 0x96, 0xdf, 0xfe, 0x71, 0xfa, 0x81, 0x71, 0xc9, 0x3f, 0x4e, 0xbf, - 0xb3, 0x5b, 0xb5, 0xf8, 0x75, 0xcf, 0x38, 0xeb, 0x03, 0x87, 0x88, 0x25, - 0xb7, 0xfc, 0xfb, 0xb5, 0x96, 0xc7, 0x76, 0x3a, 0xb0, 0xf8, 0x90, 0x9e, - 0xff, 0xd8, 0x0e, 0xa0, 0x76, 0xf7, 0x4d, 0x3a, 0xf9, 0x71, 0xbf, 0xce, - 0xbf, 0xfb, 0x67, 0xff, 0x8f, 0x32, 0xf2, 0xab, 0xce, 0x8e, 0xbf, 0xee, - 0xbe, 0xa3, 0xa2, 0xed, 0x3a, 0xba, 0x88, 0x69, 0xca, 0x17, 0x9b, 0x1b, - 0x1d, 0x70, 0x3e, 0x75, 0x4f, 0xe8, 0xff, 0xc8, 0x54, 0x6e, 0x4a, 0x23, - 0x97, 0xfe, 0x18, 0x07, 0x1e, 0x77, 0x20, 0x4e, 0xbf, 0xff, 0xf0, 0x76, - 0xc9, 0x78, 0x10, 0xaa, 0xf1, 0x9b, 0xb7, 0x02, 0x3e, 0xe8, 0xeb, 0xfe, - 0x8d, 0xc7, 0x01, 0xc8, 0x60, 0xea, 0x02, 0x3a, 0x44, 0xf7, 0x4e, 0x97, - 0xf6, 0xcc, 0xb6, 0x7f, 0xee, 0xc7, 0x5f, 0x08, 0xe7, 0xce, 0xa5, 0x68, - 0xf5, 0x5c, 0xda, 0xfe, 0xdb, 0xcc, 0xf4, 0x0f, 0xa7, 0x5f, 0xfc, 0xcf, - 0x21, 0x7f, 0xe3, 0xfc, 0x2b, 0x3a, 0x9c, 0xfe, 0x30, 0xce, 0xf7, 0x12, - 0x67, 0x5e, 0x93, 0xc8, 0xe2, 0x64, 0x9b, 0xc8, 0x76, 0x89, 0x06, 0xa3, - 0x3f, 0xfc, 0x65, 0xf3, 0xd0, 0x84, 0xf3, 0x09, 0xeb, 0xfb, 0xbd, 0x70, - 0x62, 0xce, 0xbb, 0xcf, 0xa7, 0x5e, 0xe2, 0x2c, 0xeb, 0x32, 0x75, 0x41, - 0xac, 0x08, 0xdd, 0xfa, 0x07, 0x60, 0xe8, 0xeb, 0xfe, 0x70, 0x73, 0x01, - 0xd8, 0x91, 0xd4, 0x88, 0xef, 0xf4, 0xb0, 0x51, 0x74, 0x41, 0xf2, 0x7b, - 0xda, 0xf3, 0xa3, 0xaf, 0xb7, 0xd9, 0xd4, 0x3a, 0x80, 0x78, 0x41, 0x1e, - 0xbb, 0xee, 0x75, 0xf9, 0x78, 0x2e, 0xd3, 0xaf, 0x83, 0xfc, 0xd1, 0xd7, - 0xcf, 0xd8, 0x13, 0xaf, 0xb5, 0xa7, 0xf4, 0xea, 0x74, 0x43, 0xa1, 0x2f, - 0x08, 0x58, 0x1f, 0xbf, 0x3b, 0x7d, 0x0b, 0x4e, 0xbf, 0xe4, 0x97, 0x31, - 0x91, 0x70, 0x1d, 0x7c, 0xdf, 0xe7, 0x93, 0xaf, 0x75, 0xd6, 0x75, 0x41, - 0xbe, 0x60, 0x8e, 0xfc, 0xfb, 0x79, 0xc6, 0x4e, 0xbc, 0xe2, 0xd3, 0xa9, - 0x94, 0xc0, 0xb8, 0x50, 0x2e, 0xba, 0x21, 0xf9, 0x55, 0xff, 0x9f, 0x35, - 0xe1, 0xd0, 0x1e, 0x5a, 0x75, 0xfc, 0x8c, 0x6b, 0x6c, 0x60, 0xea, 0x13, - 0xef, 0xfa, 0x05, 0xf9, 0xc1, 0xfc, 0x91, 0xd4, 0xd3, 0xc7, 0xd1, 0x0d, - 0xf4, 0x0c, 0x32, 0x75, 0xde, 0x56, 0x75, 0xff, 0x07, 0xc7, 0xc6, 0x3d, - 0xc1, 0x3a, 0xb6, 0x3f, 0x1e, 0x10, 0x08, 0xc5, 0xca, 0xa7, 0x1d, 0x7f, - 0x3a, 0xf0, 0x51, 0x43, 0xad, 0xa3, 0xa9, 0x0d, 0xdc, 0x15, 0xdd, 0xeb, - 0x95, 0x73, 0x0c, 0x15, 0x48, 0x6b, 0x98, 0x16, 0xbf, 0xd0, 0xd1, 0xcf, - 0xf1, 0x0a, 0x98, 0xd0, 0xde, 0x8d, 0xf4, 0x75, 0xf7, 0x9e, 0x47, 0xce, - 0xa0, 0x1b, 0xff, 0x8e, 0x5e, 0x71, 0x64, 0xeb, 0x85, 0xce, 0xb3, 0x27, - 0x53, 0x27, 0x81, 0xd1, 0xb8, 0x14, 0xbf, 0xf9, 0x44, 0x19, 0x69, 0xd7, - 0x1b, 0xfc, 0xeb, 0xde, 0xe2, 0xa3, 0xa9, 0x43, 0xe2, 0xea, 0x25, 0xf2, - 0xf4, 0x15, 0x9d, 0x65, 0x0e, 0xbb, 0xaa, 0x1d, 0x4e, 0x79, 0x48, 0x45, - 0xe4, 0x46, 0xff, 0xfb, 0x98, 0xdd, 0x3f, 0xdb, 0x8a, 0xf0, 0x3e, 0x9d, - 0x7f, 0xf3, 0xb5, 0x3f, 0xcc, 0xdf, 0xe1, 0x73, 0xab, 0x48, 0x94, 0xfa, - 0x8d, 0xb0, 0xea, 0x43, 0x65, 0x3c, 0x47, 0x4e, 0xa9, 0xdf, 0x18, 0x52, - 0x12, 0x3c, 0x6d, 0x88, 0x7a, 0xd1, 0xd6, 0x59, 0xd5, 0xf2, 0xea, 0x70, - 0x55, 0xd0, 0xa1, 0xd5, 0xc3, 0x70, 0x24, 0x57, 0x7d, 0xce, 0xbf, 0x3f, - 0x32, 0x74, 0x1d, 0x50, 0x6f, 0x3d, 0x15, 0xbf, 0x93, 0xf9, 0xc8, 0x50, - 0xeb, 0xfb, 0x81, 0x8d, 0xb8, 0x87, 0x5e, 0x61, 0x86, 0x0a, 0xbf, 0xe0, - 0x3e, 0xde, 0x73, 0x91, 0xb9, 0x53, 0x17, 0xf4, 0x04, 0x4b, 0xc9, 0x32, - 0xf3, 0xad, 0x0e, 0xac, 0x37, 0xb2, 0x23, 0xbe, 0x4e, 0xaa, 0x01, 0xd7, - 0xee, 0x3e, 0xf0, 0xae, 0x75, 0xff, 0xf3, 0xff, 0x40, 0xcf, 0xa7, 0x03, - 0x9b, 0xfc, 0xea, 0xe1, 0xfc, 0xfc, 0xaa, 0xdd, 0x3a, 0xe0, 0xe8, 0xeb, - 0xff, 0xf6, 0x01, 0xf3, 0x7f, 0x3f, 0x41, 0x0b, 0x73, 0x47, 0x5e, 0x88, - 0x13, 0xaf, 0xcb, 0x4f, 0xfb, 0x07, 0x56, 0xc9, 0xbc, 0xe4, 0x27, 0x15, - 0xc8, 0xa0, 0x40, 0x45, 0xbe, 0xaa, 0x11, 0x9b, 0xee, 0x7d, 0x36, 0x3a, - 0xff, 0x49, 0x34, 0x39, 0x3a, 0x0e, 0xbe, 0x7d, 0xa1, 0xa7, 0x5d, 0x9f, - 0x3a, 0xfd, 0x9b, 0x0e, 0x6e, 0x75, 0x62, 0x2c, 0x77, 0x22, 0xe9, 0x97, - 0x08, 0x44, 0x56, 0xf7, 0x1c, 0x07, 0x51, 0xd7, 0xdf, 0x5a, 0xfa, 0x75, - 0xff, 0xde, 0xb8, 0xca, 0x3f, 0xef, 0x91, 0x69, 0xd7, 0x9a, 0x9c, 0x3a, - 0xfb, 0xe3, 0x8d, 0x3a, 0xfd, 0x81, 0x9f, 0xb5, 0x07, 0x5f, 0xfe, 0x4d, - 0x73, 0x00, 0x39, 0x38, 0x73, 0x47, 0x52, 0x89, 0x8b, 0x6e, 0x44, 0xca, - 0x37, 0x46, 0xc4, 0x83, 0xe5, 0x74, 0xec, 0xeb, 0x8d, 0xa1, 0x16, 0xd2, - 0x20, 0x42, 0x73, 0x23, 0x3e, 0xde, 0x30, 0x14, 0x84, 0x9b, 0x25, 0xfd, - 0x55, 0x5b, 0x77, 0x25, 0x7b, 0xc4, 0x29, 0x3d, 0x5c, 0x9f, 0x88, 0x46, - 0x30, 0x0d, 0x47, 0x33, 0xf8, 0xc7, 0x18, 0x49, 0x9e, 0x1b, 0xf3, 0x19, - 0x05, 0xff, 0x4d, 0xf4, 0xc5, 0x5a, 0x0b, 0x9d, 0x7f, 0xff, 0xc1, 0x79, - 0xbf, 0xa4, 0xe4, 0x27, 0xf3, 0xbe, 0xae, 0x1a, 0x75, 0x4c, 0x9f, 0xd6, - 0xd1, 0xad, 0x00, 0xea, 0xfd, 0xd9, 0x44, 0x48, 0xd1, 0x5b, 0xdf, 0xfa, - 0x1b, 0x36, 0x76, 0x51, 0x12, 0x34, 0x4e, 0x16, 0x9b, 0x0f, 0xf5, 0x66, - 0x77, 0x4f, 0xe0, 0x3a, 0xe0, 0xf0, 0xeb, 0xf7, 0x65, 0x11, 0x23, 0x45, - 0xa3, 0x7d, 0x28, 0x1f, 0x4e, 0xbf, 0xe6, 0x71, 0x5f, 0x5d, 0xec, 0x7c, - 0xeb, 0xf9, 0xe0, 0x42, 0x0c, 0x3a, 0xe4, 0x50, 0xeb, 0xff, 0xf6, 0xcf, - 0xf7, 0x07, 0x5f, 0x91, 0xa1, 0xcf, 0x4e, 0xbf, 0xf3, 0xef, 0x0a, 0xfc, - 0x18, 0x57, 0xd8, 0xeb, 0xff, 0x3f, 0x7d, 0xc4, 0xce, 0xfc, 0x27, 0x53, - 0xa3, 0x57, 0x8a, 0x9a, 0x44, 0xb6, 0x32, 0x98, 0xd6, 0xa1, 0xd7, 0x7f, - 0xb9, 0xc0, 0xa8, 0xb7, 0xd1, 0xd7, 0xff, 0xe4, 0xd0, 0xe4, 0xe8, 0xf8, - 0xe6, 0xb9, 0x0c, 0x9d, 0x58, 0x88, 0x86, 0x4d, 0x2f, 0xb3, 0xd8, 0xe1, - 0xd7, 0x73, 0x47, 0x5a, 0x69, 0xf5, 0x58, 0xb4, 0xf8, 0x37, 0x82, 0xd2, - 0x33, 0x64, 0x85, 0x67, 0x9c, 0x8d, 0x13, 0xf0, 0xb7, 0x9e, 0x23, 0xf2, - 0x43, 0x7d, 0x28, 0x89, 0x1a, 0x2d, 0xab, 0xfb, 0x8e, 0xb7, 0x40, 0x1d, - 0x5d, 0x3d, 0x8f, 0x96, 0xdf, 0xfb, 0x88, 0x08, 0x68, 0x38, 0x8b, 0x3a, - 0xf9, 0xe7, 0x62, 0x1d, 0x7f, 0xce, 0xd7, 0xee, 0xcf, 0xdd, 0x8e, 0xbf, - 0xe7, 0xef, 0x8d, 0x3f, 0x21, 0x0e, 0xbf, 0xdc, 0x48, 0x6f, 0xd3, 0x63, - 0xab, 0x13, 0x23, 0x91, 0x17, 0x4f, 0x44, 0x85, 0x83, 0x99, 0xe3, 0x8b, - 0xf9, 0x48, 0xe8, 0x02, 0x27, 0x5f, 0x93, 0x65, 0xbc, 0x8e, 0xbf, 0x46, - 0xed, 0xf3, 0xa3, 0xad, 0x32, 0x87, 0xfd, 0xf2, 0xd9, 0xc4, 0xf5, 0x32, - 0x62, 0x3e, 0xc3, 0x62, 0xe5, 0xf0, 0xeb, 0xf7, 0x65, 0x11, 0x23, 0x45, - 0xcb, 0x69, 0x80, 0x79, 0x38, 0x2d, 0x7f, 0xa6, 0xce, 0xca, 0x22, 0x46, - 0x8b, 0xb6, 0x9d, 0xd4, 0x05, 0x6c, 0x52, 0xd9, 0xd5, 0x10, 0x46, 0xce, - 0xa4, 0xf6, 0x4a, 0x56, 0x4a, 0xea, 0xf0, 0xb6, 0xe4, 0xb3, 0xe1, 0x96, - 0x75, 0xa7, 0x4f, 0x94, 0x5f, 0xe9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0xa7, - 0xb7, 0xce, 0xbf, 0xe7, 0x8d, 0xbc, 0x6f, 0xa7, 0x01, 0xd4, 0x87, 0x96, - 0x22, 0x17, 0xd2, 0x88, 0x91, 0xa2, 0xb9, 0xbf, 0xd3, 0x67, 0x65, 0x11, - 0x23, 0x45, 0x9d, 0x5d, 0x3e, 0xce, 0x16, 0xdf, 0xfe, 0xfb, 0xeb, 0xc0, - 0x75, 0xf7, 0x65, 0x94, 0x3a, 0xff, 0x3f, 0x3c, 0x2e, 0x7c, 0x9f, 0x7e, - 0x75, 0x62, 0x23, 0x27, 0x26, 0xdf, 0xbb, 0x9f, 0x45, 0x9d, 0x7d, 0x02, - 0xe0, 0x3a, 0xfe, 0xc6, 0x5d, 0x6f, 0xe4, 0xeb, 0xf7, 0x65, 0x11, 0x23, - 0x44, 0x85, 0x7f, 0xec, 0x5e, 0x47, 0x76, 0xf1, 0xba, 0xce, 0xbf, 0xe4, - 0xdf, 0x5f, 0x17, 0x5e, 0x8e, 0xb9, 0xb3, 0x62, 0x2b, 0x38, 0x67, 0xea, - 0x0d, 0xf4, 0xf9, 0xc7, 0x59, 0xd7, 0xfb, 0x39, 0xad, 0x67, 0x76, 0x3a, - 0xd3, 0x01, 0x58, 0x9e, 0x42, 0x31, 0x21, 0x5d, 0xd2, 0x45, 0x93, 0x70, - 0x7e, 0x21, 0xb5, 0xa3, 0xdf, 0x93, 0x5f, 0xfd, 0x37, 0x23, 0x43, 0x9f, - 0xfb, 0xfa, 0x75, 0xff, 0xe9, 0x97, 0x0d, 0x9b, 0x3b, 0x28, 0x89, 0x1a, - 0x27, 0xca, 0x92, 0xe6, 0x5a, 0xbc, 0xb9, 0xd5, 0xc2, 0x4f, 0x88, 0x97, - 0x9a, 0x9b, 0x9d, 0x7e, 0xce, 0xe6, 0x32, 0x75, 0xa6, 0xe1, 0xe1, 0x79, - 0x1c, 0xbf, 0x76, 0x51, 0x12, 0x34, 0x56, 0x57, 0xfe, 0x86, 0xcd, 0x9d, - 0x94, 0x44, 0x8d, 0x13, 0x75, 0xa6, 0xc3, 0xfd, 0x59, 0x9d, 0x49, 0x1a, - 0x09, 0x0a, 0x8b, 0xf7, 0x65, 0x11, 0x23, 0x44, 0xad, 0x7e, 0x17, 0x04, - 0x70, 0xeb, 0xf4, 0xcb, 0x86, 0xcd, 0x87, 0xb0, 0x86, 0x77, 0xfe, 0x4d, - 0x05, 0x62, 0x93, 0x83, 0x07, 0x5f, 0xce, 0x31, 0x28, 0x57, 0x3a, 0x9a, - 0x7d, 0x6b, 0x3e, 0xbf, 0x76, 0x51, 0x12, 0x34, 0x4b, 0x97, 0xfc, 0x90, - 0xdf, 0x8b, 0xaf, 0x47, 0x5f, 0x4e, 0x41, 0x73, 0xaf, 0xff, 0xd1, 0xf4, - 0x0b, 0x45, 0x1a, 0xff, 0x10, 0xb4, 0xeb, 0xff, 0xc8, 0x29, 0xee, 0xba, - 0xe8, 0xd8, 0xd1, 0xd7, 0xe9, 0x97, 0x0d, 0x99, 0xd3, 0x45, 0xc2, 0x2e, - 0x19, 0xc1, 0xb6, 0x88, 0x7e, 0xa5, 0x7f, 0xf4, 0xd0, 0xd9, 0xb3, 0xb2, - 0x88, 0x91, 0xa2, 0x3b, 0xbf, 0xef, 0xf3, 0x1b, 0x34, 0x0e, 0x8e, 0xbf, - 0xa7, 0xf1, 0x79, 0x60, 0x9d, 0x70, 0x78, 0x75, 0xfd, 0x3e, 0x8e, 0x72, - 0x3e, 0x75, 0xfe, 0xc6, 0x34, 0xe3, 0xfd, 0x1d, 0x7f, 0xe7, 0x10, 0xfd, - 0x22, 0x74, 0x34, 0xeb, 0xe9, 0x44, 0x48, 0xd1, 0x50, 0xd4, 0x8f, 0xab, - 0xa7, 0xb7, 0x37, 0x0e, 0xbf, 0xe6, 0xfd, 0x3b, 0x12, 0x41, 0x3a, 0xff, - 0xf9, 0xe1, 0x79, 0xd1, 0xc4, 0x9c, 0x9d, 0x83, 0xaf, 0xf9, 0xda, 0xfd, - 0xd9, 0xfb, 0xb1, 0xd7, 0xf4, 0xe8, 0x5f, 0x18, 0x83, 0xaf, 0xff, 0xf2, - 0x3f, 0xe3, 0x93, 0x6b, 0x98, 0x3f, 0xf1, 0xeb, 0x74, 0x75, 0xb1, 0x11, - 0x24, 0x25, 0xf7, 0xdc, 0xfe, 0x6c, 0x75, 0xfb, 0x36, 0x81, 0x9c, 0x75, - 0xff, 0xff, 0xfe, 0x76, 0xf8, 0xff, 0x11, 0xf5, 0xe3, 0x03, 0x27, 0x9d, - 0xe3, 0x3b, 0xdc, 0x9c, 0x18, 0xe1, 0xd7, 0xdc, 0x18, 0x54, 0x75, 0x62, - 0x60, 0x42, 0x45, 0xa2, 0x8f, 0xc2, 0x5a, 0xff, 0xff, 0x83, 0x0a, 0xe9, - 0xb7, 0x21, 0x3e, 0xfc, 0x4f, 0xeb, 0x00, 0x75, 0xa6, 0x9f, 0x57, 0x19, - 0x67, 0xc2, 0xf9, 0xfc, 0x5b, 0x63, 0x0c, 0x84, 0xe4, 0x88, 0xb7, 0x15, - 0xe9, 0xb0, 0xa6, 0x6a, 0x19, 0x7f, 0x8c, 0xa2, 0x79, 0x06, 0xfa, 0x51, - 0x12, 0x34, 0x55, 0x17, 0xfb, 0xaf, 0x3b, 0x76, 0xe7, 0xce, 0xae, 0x9f, - 0x10, 0x4b, 0x6f, 0xfd, 0x0d, 0x9b, 0x3b, 0x28, 0x89, 0x1a, 0x26, 0xbb, - 0x4d, 0x87, 0xd8, 0xb2, 0x2b, 0xf7, 0x65, 0x11, 0x23, 0x45, 0x59, 0x7f, - 0xce, 0xd7, 0xee, 0xcf, 0xdd, 0x8e, 0xb4, 0xd8, 0x7d, 0x82, 0x67, 0x7f, - 0xe9, 0xb8, 0xfb, 0xfd, 0xf9, 0x0a, 0xe7, 0x5f, 0xfd, 0x34, 0x36, 0x6c, - 0xec, 0xa2, 0x24, 0x68, 0x91, 0x2f, 0xdd, 0x94, 0x44, 0x8d, 0x16, 0x95, - 0xff, 0xa1, 0xb3, 0x67, 0x65, 0x11, 0x23, 0x44, 0xfb, 0x69, 0xb0, 0xff, - 0x56, 0x67, 0x7f, 0xfa, 0x65, 0xc3, 0x66, 0xce, 0xca, 0x22, 0x46, 0x8a, - 0x12, 0xfd, 0xc4, 0xd9, 0xfa, 0x75, 0xfb, 0xb2, 0x88, 0x91, 0xa2, 0x8f, - 0xbf, 0xe7, 0x6b, 0xf7, 0x67, 0xee, 0xc7, 0x5f, 0xf8, 0x5d, 0x97, 0x17, - 0x67, 0x8e, 0x75, 0xff, 0xfd, 0x80, 0xe3, 0xf9, 0x9b, 0xe3, 0x1e, 0xeb, - 0x4f, 0xe9, 0x57, 0xe9, 0x97, 0x0d, 0x99, 0xd3, 0x2d, 0xc2, 0x71, 0x33, - 0xf9, 0xcc, 0xf1, 0xe5, 0x3b, 0x33, 0x47, 0x68, 0xfb, 0xda, 0xe9, 0x8a, - 0x2a, 0x4e, 0x4e, 0xca, 0x39, 0xfd, 0xe1, 0x28, 0x84, 0xec, 0xa1, 0x72, - 0x19, 0xde, 0x94, 0x7e, 0x38, 0x4b, 0xfd, 0x36, 0x76, 0x51, 0x12, 0x34, - 0x44, 0x57, 0xf6, 0x76, 0x51, 0x12, 0x34, 0x45, 0x77, 0xfc, 0xaf, 0x36, - 0x76, 0x51, 0x12, 0x34, 0x57, 0x15, 0x32, 0x20, 0x20, 0xe2, 0xff, 0xf7, - 0xae, 0x32, 0x9a, 0x3f, 0xef, 0x91, 0x69, 0xd7, 0xd3, 0x6c, 0xca, 0xb9, - 0xd6, 0x4d, 0xcf, 0xd7, 0xd4, 0xdb, 0xec, 0xe4, 0x7c, 0xeb, 0xfd, 0x89, - 0xdf, 0x7d, 0x0e, 0x8e, 0xb4, 0xfa, 0x27, 0xa9, 0xa2, 0x0b, 0xff, 0xfb, - 0xfa, 0x4e, 0x42, 0x35, 0x07, 0xe1, 0xe7, 0x70, 0xeb, 0xf7, 0x65, 0x11, - 0x23, 0x45, 0x3d, 0x7f, 0x96, 0x80, 0x0c, 0x75, 0xa7, 0x5c, 0xb4, 0x3a, - 0x9c, 0xf1, 0xe4, 0x65, 0x7f, 0xff, 0x77, 0xa1, 0xef, 0x5c, 0x71, 0x44, - 0xe7, 0x33, 0xc9, 0xd7, 0xff, 0x23, 0x70, 0x7d, 0x75, 0xa7, 0x5a, 0x75, - 0xfe, 0x6b, 0xf7, 0x67, 0xee, 0xc7, 0x5f, 0x78, 0x18, 0x69, 0xd7, 0xe8, - 0xce, 0x22, 0xce, 0xad, 0x1e, 0x3c, 0xe2, 0x2a, 0x74, 0x4f, 0xe3, 0xdd, - 0xff, 0x38, 0xcb, 0x27, 0x67, 0xf4, 0x75, 0x4f, 0xea, 0xad, 0x5c, 0xb3, - 0x16, 0x24, 0xf4, 0x84, 0x30, 0xb8, 0x30, 0xe1, 0x9c, 0x43, 0x7f, 0xfa, - 0x1b, 0x30, 0x06, 0x18, 0xd6, 0x9f, 0xd3, 0xaf, 0xff, 0x7c, 0x73, 0xd8, - 0x1f, 0x66, 0x5a, 0x2c, 0xea, 0x99, 0x30, 0xf0, 0x3d, 0x22, 0x5d, 0xc0, - 0xc3, 0xaf, 0xfe, 0x40, 0x76, 0x37, 0x9b, 0xbd, 0x7d, 0x8e, 0xa9, 0x8f, - 0x6f, 0x82, 0xb7, 0x01, 0xce, 0xbf, 0xff, 0x71, 0xfb, 0x8d, 0x48, 0xfe, - 0x01, 0x03, 0x23, 0xaf, 0xce, 0xdf, 0x42, 0xd3, 0xaf, 0xa5, 0x11, 0x23, - 0x45, 0x67, 0x4c, 0x9e, 0xaf, 0x4a, 0x2f, 0xbe, 0x8b, 0xd1, 0xd7, 0xf6, - 0xcb, 0x71, 0x6e, 0x8e, 0xbf, 0x67, 0xf5, 0xe7, 0x47, 0x5e, 0x7d, 0x90, - 0xeb, 0xf7, 0xfd, 0xf2, 0x2d, 0x3a, 0xf0, 0x63, 0x47, 0x5f, 0xf6, 0x35, - 0x02, 0xaf, 0x3e, 0x7a, 0xb3, 0xaf, 0xd8, 0xce, 0xc1, 0xf4, 0xeb, 0x4c, - 0xea, 0x88, 0x40, 0x2b, 0x90, 0xa7, 0xdc, 0x8f, 0xa4, 0x2b, 0x2d, 0xe1, - 0x4c, 0x0d, 0x89, 0x56, 0x86, 0xfc, 0xa0, 0xdf, 0xfb, 0x89, 0xf8, 0xee, - 0xce, 0x80, 0x3a, 0xfd, 0xf4, 0x1c, 0x59, 0xd7, 0xcd, 0x81, 0x9b, 0x0f, - 0x89, 0x51, 0xed, 0xff, 0xd3, 0x43, 0x66, 0xce, 0xca, 0x22, 0x46, 0x89, - 0x16, 0xfe, 0xce, 0xca, 0x22, 0x46, 0x8b, 0x26, 0xff, 0xf7, 0xf5, 0xe7, - 0x53, 0x66, 0xc8, 0x2d, 0xd1, 0xd5, 0x32, 0x21, 0x70, 0xe2, 0xfe, 0xce, - 0xca, 0x22, 0x46, 0x8b, 0x62, 0xff, 0xfe, 0x9f, 0x79, 0xe0, 0x73, 0xbf, - 0xd7, 0x19, 0xf1, 0xe3, 0x93, 0xc7, 0x5e, 0xe8, 0x78, 0x75, 0xdf, 0x99, - 0xd1, 0x0f, 0xd6, 0xba, 0x99, 0x1d, 0xc9, 0x0b, 0xfb, 0xd9, 0xac, 0x3a, - 0xfa, 0x51, 0x12, 0x34, 0x5b, 0x77, 0xda, 0xda, 0x3a, 0x75, 0x74, 0xf3, - 0xfe, 0x5b, 0x7f, 0x27, 0x3e, 0x9e, 0x84, 0xeb, 0xfe, 0x76, 0xbf, 0x76, - 0x7e, 0xec, 0x75, 0xa6, 0x6a, 0x3c, 0x71, 0xa5, 0x92, 0x21, 0x2d, 0xbd, - 0x3f, 0xf0, 0x07, 0x5e, 0xdb, 0x88, 0x75, 0xff, 0xa7, 0xf9, 0xfd, 0x5b, - 0x7f, 0x98, 0x2f, 0xe9, 0xd7, 0xf3, 0x8b, 0x40, 0x15, 0x9d, 0x7e, 0xec, - 0xa2, 0x24, 0x68, 0xbc, 0x2f, 0xbf, 0x3d, 0x9c, 0x3a, 0xfc, 0xb7, 0x16, - 0xc1, 0xd7, 0xfe, 0xf2, 0xbd, 0xdb, 0xfc, 0x1f, 0xe8, 0xeb, 0xb1, 0x43, - 0xa9, 0xcf, 0x5f, 0x10, 0x6f, 0x93, 0x6c, 0x59, 0xd7, 0xec, 0x1f, 0x55, - 0x39, 0xd7, 0xe7, 0xf2, 0x18, 0xd1, 0xd7, 0xff, 0x67, 0x39, 0x0d, 0x5a, - 0x3f, 0x5a, 0x75, 0xcf, 0xe9, 0xd4, 0xd3, 0xd8, 0xfa, 0x15, 0x4f, 0xaa, - 0xa5, 0x67, 0xf2, 0x15, 0x6f, 0x1c, 0xd9, 0x3b, 0x0b, 0x37, 0x33, 0x42, - 0x4e, 0x3e, 0x41, 0x07, 0xa4, 0x22, 0x51, 0xf8, 0x40, 0x5f, 0xed, 0xe6, - 0xcf, 0x63, 0xba, 0x3a, 0xa6, 0x47, 0x8b, 0xc2, 0xf2, 0xf2, 0x66, 0xe7, - 0x5f, 0x4a, 0x22, 0x46, 0x8b, 0xd2, 0xff, 0xc9, 0xfe, 0x0c, 0x37, 0xd8, - 0xf4, 0xea, 0xe9, 0xf5, 0xac, 0xb6, 0xf2, 0xd3, 0xe7, 0x5f, 0xf4, 0x7d, - 0xae, 0xa7, 0xd3, 0x63, 0xa9, 0x67, 0xa8, 0x23, 0x77, 0xec, 0x5f, 0x20, - 0x07, 0x5a, 0x60, 0x26, 0x87, 0x90, 0x86, 0xf2, 0xec, 0xa8, 0x86, 0x9d, - 0xb2, 0x2a, 0xda, 0x17, 0xed, 0x84, 0xc6, 0x4e, 0x20, 0xca, 0x11, 0x89, - 0x29, 0x11, 0x98, 0xc1, 0xfa, 0x74, 0xb8, 0x6b, 0x7b, 0x18, 0x88, 0xc6, - 0x32, 0x19, 0x79, 0x2c, 0x46, 0xd7, 0x70, 0x78, 0x75, 0xff, 0xc1, 0x76, - 0x47, 0x27, 0x42, 0xd6, 0x87, 0x5f, 0x67, 0x23, 0xe7, 0x5f, 0xec, 0x4e, - 0xfb, 0xe8, 0x74, 0x75, 0xa7, 0xd5, 0x11, 0x30, 0x28, 0x9a, 0x20, 0xbf, - 0x27, 0xdf, 0x7d, 0x8e, 0xbf, 0x76, 0x51, 0x12, 0x34, 0x44, 0x77, 0xff, - 0xdc, 0x0e, 0xb5, 0x8b, 0x1c, 0x9d, 0xe1, 0xd5, 0x93, 0xaf, 0xfc, 0xd7, - 0xdb, 0xb9, 0xff, 0xa7, 0xce, 0xbf, 0xec, 0xee, 0x6b, 0x20, 0x76, 0x3a, - 0xff, 0xff, 0x72, 0x13, 0xef, 0xc1, 0xcf, 0xf1, 0x39, 0x88, 0xc1, 0xd7, - 0xff, 0xff, 0xbf, 0xf4, 0x5f, 0x53, 0x37, 0x10, 0xfd, 0xf9, 0xe2, 0x72, - 0x7d, 0x97, 0x3a, 0x9d, 0x1b, 0x18, 0xbb, 0x76, 0xcb, 0x2a, 0xe6, 0x18, - 0x2a, 0xff, 0xd3, 0x4b, 0x88, 0xcf, 0x1f, 0x69, 0xbd, 0x35, 0xec, 0x0b, - 0xdf, 0x4e, 0x7f, 0xb9, 0xd4, 0xd3, 0xfd, 0x45, 0xbb, 0xfb, 0x21, 0x79, - 0xbf, 0xce, 0xb9, 0x5a, 0x57, 0x3a, 0xfe, 0x57, 0x1c, 0xe4, 0x7c, 0xeb, - 0xf9, 0xd4, 0xc1, 0x45, 0x0e, 0xbf, 0xb3, 0xea, 0xbf, 0x9c, 0x3a, 0xb1, - 0x11, 0x02, 0x5d, 0xa2, 0xcb, 0xff, 0xfa, 0x53, 0x76, 0x05, 0x3f, 0x37, - 0x5f, 0xe3, 0x1e, 0x9d, 0x53, 0xe2, 0xe9, 0x84, 0xff, 0x0a, 0xe7, 0x3b, - 0xc2, 0x89, 0x19, 0xee, 0xae, 0x87, 0xdd, 0x8c, 0x3a, 0x21, 0x9b, 0xe9, - 0x0e, 0x8b, 0x3f, 0x0a, 0x69, 0xc5, 0xd7, 0x2a, 0xe1, 0xd7, 0xee, 0xca, - 0x22, 0x46, 0x88, 0xba, 0xfd, 0xff, 0x7c, 0x8b, 0x4a, 0xb4, 0xdb, 0x1f, - 0xae, 0x0c, 0x41, 0x9d, 0x4c, 0x9b, 0xf3, 0x63, 0x49, 0xbf, 0xf9, 0x70, - 0xd9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x66, 0xbf, 0x95, 0x8a, 0xb6, 0x9f, - 0x74, 0xff, 0x3a, 0xf6, 0xef, 0xa3, 0xaf, 0x49, 0x16, 0x75, 0xd3, 0xca, - 0xd1, 0xd7, 0x60, 0x4e, 0xbf, 0xfd, 0xc7, 0x5c, 0x7f, 0x37, 0xf5, 0x7e, - 0x78, 0x75, 0xfd, 0xfc, 0xdb, 0x3d, 0x64, 0xeb, 0xfd, 0xe3, 0x06, 0x3b, - 0xec, 0xf1, 0xd7, 0xff, 0xe5, 0xc7, 0x33, 0x7f, 0x78, 0xc4, 0x71, 0x9e, - 0x04, 0xea, 0x02, 0x24, 0x30, 0xde, 0xed, 0x61, 0xd7, 0xde, 0xba, 0xaf, - 0x9d, 0x7f, 0xff, 0xe4, 0x17, 0x90, 0xba, 0xfc, 0x3f, 0x7a, 0x93, 0xbb, - 0x11, 0xe9, 0xd4, 0xad, 0x2a, 0x06, 0x90, 0xf2, 0x0a, 0xb2, 0x9b, 0xc8, - 0x5f, 0xc1, 0x17, 0xa2, 0xbf, 0x24, 0xbf, 0x98, 0x71, 0x1c, 0xf9, 0xd7, - 0xd1, 0xc4, 0x64, 0xeb, 0xee, 0x32, 0xe0, 0x3a, 0xb0, 0xfb, 0xa4, 0x57, - 0x04, 0x36, 0x91, 0xd7, 0xff, 0xef, 0x77, 0x6f, 0x02, 0xfd, 0x9b, 0x89, - 0x28, 0xe9, 0xd7, 0xff, 0xfe, 0x45, 0xa7, 0x78, 0x1d, 0x35, 0xe7, 0x75, - 0xc7, 0xfc, 0xc6, 0x9d, 0x7f, 0xe4, 0xfa, 0x49, 0x01, 0xfc, 0x91, 0xd5, - 0xf4, 0x54, 0x2a, 0x6c, 0xbe, 0xfc, 0xf6, 0x70, 0xeb, 0xff, 0xfd, 0x03, - 0x21, 0xc0, 0x70, 0x3e, 0x38, 0xed, 0xeb, 0xec, 0x75, 0x62, 0x21, 0x42, - 0x49, 0x7f, 0xff, 0xa1, 0x41, 0xcf, 0x43, 0xaf, 0x0d, 0x4e, 0x3c, 0x86, - 0x0e, 0xbe, 0xfa, 0x71, 0x0e, 0xbf, 0xe8, 0xeb, 0x7c, 0x64, 0x81, 0x87, - 0x53, 0xaa, 0x86, 0xc8, 0xc0, 0x39, 0x0a, 0xa8, 0x22, 0x16, 0x10, 0x90, - 0x5b, 0xa7, 0x5f, 0xdf, 0xc5, 0xef, 0x8b, 0x3a, 0xdc, 0xc3, 0x7a, 0x82, - 0x17, 0xff, 0xe0, 0x20, 0xed, 0x9a, 0x48, 0xe4, 0xcc, 0x30, 0xc1, 0x57, - 0xf7, 0xf8, 0xfb, 0x70, 0x27, 0x5f, 0xdb, 0xb7, 0x5e, 0x85, 0x93, 0xaf, - 0xfb, 0x6c, 0xf4, 0x01, 0x8e, 0xb4, 0xeb, 0xd1, 0x12, 0x34, 0x59, 0xf7, - 0xf7, 0xb0, 0x2d, 0x45, 0x9d, 0x5b, 0x22, 0x36, 0x47, 0x5e, 0x93, 0xdf, - 0xf9, 0x38, 0xed, 0x4f, 0xbf, 0xf4, 0x75, 0xff, 0xf2, 0x77, 0x91, 0xe3, - 0x27, 0x0e, 0x6b, 0x04, 0xeb, 0xcc, 0x30, 0xc1, 0x57, 0xfe, 0x86, 0xe8, - 0x72, 0x40, 0xce, 0x95, 0x31, 0x7f, 0x7f, 0xc1, 0xff, 0x32, 0x77, 0x86, - 0xac, 0xeb, 0xff, 0x6e, 0xd1, 0x0f, 0xbe, 0x24, 0xbf, 0x4e, 0xb9, 0xd4, - 0x3a, 0x9c, 0xf6, 0xb6, 0x44, 0xbf, 0xdc, 0x40, 0x0c, 0x43, 0x27, 0x5f, - 0xe0, 0x70, 0x31, 0xec, 0xf6, 0x1d, 0x4e, 0x7c, 0xe8, 0x63, 0x7f, 0xc8, - 0x20, 0xf2, 0x00, 0xff, 0x47, 0x53, 0x57, 0x02, 0xe4, 0x4b, 0xba, 0xc3, - 0x25, 0xdd, 0x85, 0xf2, 0xcc, 0xb8, 0x79, 0xeb, 0x70, 0xa6, 0x6a, 0x12, - 0xff, 0x84, 0x4c, 0xe2, 0x0b, 0xfe, 0xec, 0x31, 0xc4, 0x7e, 0xb9, 0xd7, - 0xfe, 0xea, 0x69, 0xbe, 0x78, 0xe2, 0xe7, 0x5f, 0x75, 0x1d, 0x67, 0x5f, - 0xff, 0xbe, 0xa0, 0x5f, 0x01, 0xcc, 0xd6, 0xed, 0x7e, 0x1d, 0x5d, 0x45, - 0xa2, 0xcf, 0x84, 0x82, 0xe8, 0x69, 0xd7, 0xff, 0xff, 0xf0, 0xc3, 0x1f, - 0xce, 0x0e, 0x7c, 0x3e, 0xae, 0x1b, 0x00, 0x71, 0x8e, 0xc3, 0x4e, 0xbf, - 0xd9, 0xce, 0x07, 0xf0, 0x27, 0x59, 0x00, 0x8c, 0xb6, 0x45, 0x7b, 0x08, - 0x5b, 0xf7, 0x59, 0x9d, 0x80, 0x3a, 0xff, 0xd8, 0xc2, 0xae, 0xe2, 0xa1, - 0x0b, 0x07, 0x53, 0xa7, 0x45, 0xc8, 0x7d, 0x41, 0xd8, 0x95, 0x5f, 0xff, - 0xff, 0xb3, 0xdd, 0x66, 0x0a, 0x9e, 0x7a, 0x2f, 0x9c, 0x9b, 0x43, 0x9b, - 0x2f, 0x16, 0x75, 0xfa, 0x74, 0x71, 0xfc, 0x9d, 0x58, 0x8a, 0xe4, 0x84, - 0x25, 0xed, 0x3e, 0xc7, 0x5e, 0x9e, 0xce, 0x1d, 0x4d, 0x3e, 0x0d, 0x13, - 0x7c, 0x72, 0xf7, 0x02, 0xc1, 0xd7, 0xbd, 0x0c, 0x8e, 0xbd, 0xfc, 0xf2, - 0x75, 0xfc, 0xfb, 0xeb, 0xc7, 0x5c, 0xeb, 0xc0, 0x0c, 0x8e, 0xbe, 0x00, - 0xbb, 0x4e, 0xa4, 0x37, 0x90, 0x39, 0x7c, 0xff, 0xd3, 0x9d, 0x40, 0x4c, - 0x07, 0x71, 0xd4, 0x1d, 0x58, 0xef, 0x1a, 0xe7, 0x87, 0xee, 0xc9, 0x1d, - 0x7f, 0x75, 0x27, 0x60, 0xe8, 0xeb, 0xf7, 0x05, 0xf3, 0xa6, 0x5f, 0xf9, - 0x3a, 0xdc, 0xee, 0xc1, 0x80, 0x1a, 0x20, 0xd9, 0x8d, 0x2d, 0xfa, 0x24, - 0x8b, 0x73, 0xaf, 0xe6, 0xf0, 0x63, 0x7f, 0x9d, 0x6c, 0x91, 0xe9, 0x09, - 0x2d, 0xfe, 0x6a, 0x2d, 0xf9, 0xe4, 0x07, 0x5f, 0xfe, 0x7c, 0x1d, 0xff, - 0x9d, 0x4d, 0xa1, 0x67, 0x5f, 0xa1, 0x8f, 0xe7, 0x34, 0x7f, 0x9f, 0x34, - 0xa9, 0xf1, 0x3f, 0x67, 0x15, 0x6a, 0x96, 0x42, 0xb8, 0x61, 0x45, 0x7b, - 0x58, 0xd3, 0xaf, 0xc9, 0xbb, 0x50, 0x4e, 0xbc, 0x9c, 0xc3, 0xae, 0x75, - 0xe1, 0xe0, 0x48, 0x9a, 0xfd, 0x80, 0xd7, 0x1c, 0xea, 0x74, 0x56, 0xa2, - 0xdf, 0x4b, 0x2f, 0x73, 0x04, 0xeb, 0xff, 0xe8, 0x53, 0xef, 0xdf, 0x7a, - 0xff, 0x18, 0xf4, 0xeb, 0xff, 0xf8, 0x61, 0x4f, 0x1e, 0x46, 0x3f, 0xa4, - 0xdf, 0x88, 0xc1, 0xd5, 0x88, 0xc9, 0x11, 0xa0, 0xa8, 0x5f, 0x20, 0xc0, - 0x0e, 0xbf, 0xf2, 0xf3, 0xfa, 0xf3, 0xa8, 0x6e, 0x1d, 0x7e, 0xd3, 0xf7, - 0xee, 0x74, 0xc6, 0xfe, 0x80, 0x89, 0x5d, 0x2f, 0x5f, 0xbc, 0xb3, 0x11, - 0xd3, 0xaf, 0xb9, 0x89, 0x38, 0xeb, 0xfb, 0x49, 0xdc, 0x0f, 0x4e, 0xbf, - 0xff, 0xce, 0xcf, 0x84, 0x90, 0x7b, 0xa0, 0xf8, 0x5a, 0x7f, 0x88, 0x75, - 0x22, 0x3f, 0xd6, 0x47, 0xc2, 0x9f, 0x91, 0x2a, 0x2c, 0xb9, 0x73, 0xe9, - 0xa2, 0xfc, 0xbf, 0xf9, 0xbf, 0x0b, 0x5a, 0xbf, 0xfd, 0xd6, 0x75, 0xfe, - 0xfe, 0x9f, 0x6c, 0xd0, 0x0e, 0xbf, 0xfe, 0xe3, 0x83, 0x25, 0xe3, 0x07, - 0x01, 0xc7, 0x3a, 0xff, 0xe4, 0xc1, 0xcc, 0xd7, 0x86, 0xe9, 0x67, 0x56, - 0xe9, 0x84, 0xa2, 0x2b, 0x26, 0x7a, 0x4e, 0xbc, 0xa3, 0xf4, 0xeb, 0xf8, - 0x0f, 0xef, 0x73, 0x73, 0xaa, 0x63, 0xca, 0x58, 0xe5, 0xfe, 0x75, 0xe2, - 0x75, 0x96, 0x9d, 0x72, 0x32, 0x75, 0xff, 0xef, 0xbf, 0x06, 0x36, 0x7e, - 0xf6, 0x1a, 0x75, 0xef, 0xa6, 0xc7, 0x5e, 0x17, 0x91, 0xd7, 0xff, 0x01, - 0x19, 0xe3, 0xf7, 0x76, 0xbf, 0x4e, 0xbf, 0xfe, 0x17, 0x97, 0x8e, 0xe2, - 0x06, 0x7e, 0xc5, 0x58, 0x75, 0x78, 0x4c, 0xb9, 0x05, 0x96, 0x90, 0x23, - 0x9a, 0x1a, 0x54, 0x8b, 0x4e, 0xaf, 0x88, 0x09, 0x79, 0x19, 0x8a, 0x42, - 0x27, 0x84, 0x71, 0x1b, 0x05, 0xff, 0x60, 0xb4, 0x71, 0x6f, 0x23, 0xaf, - 0xdc, 0x49, 0xd8, 0x03, 0xaf, 0xd0, 0xb4, 0x55, 0x87, 0x5e, 0xfb, 0xee, - 0x75, 0x61, 0xe1, 0xc1, 0x3d, 0xff, 0xff, 0x9f, 0x88, 0xb9, 0x99, 0x6c, - 0x77, 0xcf, 0x13, 0x7d, 0x49, 0x36, 0x3a, 0x80, 0x99, 0x8a, 0x86, 0xac, - 0xb5, 0xaa, 0x20, 0xbf, 0xa3, 0xaf, 0xcf, 0x20, 0x3a, 0xf9, 0xd3, 0x67, - 0x3a, 0xf9, 0x88, 0xcd, 0x1d, 0x7f, 0xcd, 0x5c, 0x37, 0xfa, 0x75, 0x0e, - 0xa7, 0x3d, 0xa8, 0x21, 0xbd, 0xa4, 0x13, 0xaf, 0xc3, 0x2f, 0x1a, 0xdc, - 0xea, 0xc3, 0xc4, 0x81, 0xaa, 0x84, 0xcb, 0x3d, 0x2e, 0x17, 0xa0, 0xb2, - 0x5d, 0xb3, 0x4e, 0xbc, 0x9c, 0x43, 0xab, 0x73, 0x63, 0xf1, 0x7b, 0xef, - 0x21, 0x8d, 0x1d, 0x7d, 0xef, 0xb9, 0xb9, 0xd7, 0xd0, 0xdd, 0xfd, 0x3a, - 0xfd, 0xfc, 0x81, 0x91, 0xd4, 0x27, 0x90, 0xa8, 0x8e, 0xff, 0x83, 0x0d, - 0x06, 0x67, 0xba, 0x3a, 0xff, 0x7a, 0x9b, 0xee, 0xdc, 0xf9, 0xd5, 0xc3, - 0xed, 0xd1, 0xc5, 0xfc, 0xfb, 0xe9, 0x68, 0xae, 0x75, 0xfd, 0x1b, 0x7b, - 0x02, 0x03, 0xab, 0xa9, 0xbd, 0xf1, 0xb3, 0xf0, 0x90, 0x9c, 0x45, 0x3c, - 0x61, 0x7f, 0xdc, 0xf2, 0xf2, 0x9e, 0xce, 0xb9, 0xd4, 0xea, 0x8b, 0xf2, - 0x39, 0xe8, 0x55, 0xb9, 0x90, 0x9d, 0x65, 0x9d, 0x5b, 0x9a, 0x79, 0xf8, - 0x5e, 0xfe, 0x8d, 0xda, 0x2e, 0x03, 0xaf, 0xf9, 0xf7, 0x6a, 0x0a, 0xe3, - 0xe7, 0x54, 0x1f, 0x18, 0x96, 0x5f, 0xa1, 0xb9, 0xb3, 0x9d, 0x7f, 0xf2, - 0x3e, 0x86, 0x1b, 0xe3, 0x59, 0xd3, 0xaf, 0xff, 0xf2, 0x6b, 0x6c, 0x63, - 0x04, 0x2a, 0x9e, 0x6c, 0x18, 0xe9, 0xd7, 0xfb, 0x76, 0xe9, 0x96, 0xbe, - 0xc7, 0x50, 0x13, 0x00, 0x12, 0x6f, 0xa1, 0x85, 0x86, 0xff, 0xff, 0xdc, - 0x4d, 0xff, 0x9b, 0xff, 0xbd, 0x7f, 0xfb, 0xe4, 0x5b, 0xcc, 0x3a, 0xf8, - 0x00, 0x81, 0x3a, 0xff, 0xd1, 0xc9, 0x24, 0x78, 0xd4, 0x70, 0xeb, 0xfd, - 0xc4, 0x52, 0x78, 0x3d, 0x50, 0xeb, 0xfe, 0x76, 0x17, 0xc7, 0x41, 0xd8, - 0xeb, 0xff, 0xe1, 0xcd, 0x62, 0xde, 0x59, 0xf4, 0xee, 0x1d, 0x6c, 0x92, - 0x2e, 0xfe, 0x71, 0x38, 0xe2, 0xff, 0xb8, 0x91, 0xee, 0x02, 0x1a, 0x75, - 0x3a, 0xbd, 0xe0, 0x42, 0x2b, 0x23, 0x20, 0x91, 0xea, 0x38, 0x70, 0x80, - 0x61, 0xf3, 0xf3, 0x7b, 0xff, 0xb0, 0x7d, 0xcc, 0xee, 0xbe, 0xf8, 0x75, - 0xff, 0x6f, 0xfc, 0xea, 0x6d, 0x0b, 0x3a, 0xd9, 0xe9, 0xfd, 0x0a, 0x0d, - 0xff, 0xb1, 0x5e, 0x07, 0xdf, 0x13, 0xf3, 0x50, 0xeb, 0xff, 0xf3, 0x8b, - 0x73, 0x88, 0xb0, 0x63, 0x2f, 0x9d, 0x3a, 0xfc, 0xf2, 0xe2, 0x32, 0x75, - 0xfd, 0xee, 0xa4, 0xfd, 0x50, 0xeb, 0xfd, 0x8d, 0xc4, 0x07, 0x10, 0xeb, - 0xef, 0xb5, 0x7c, 0x3a, 0xf9, 0x14, 0x46, 0x0e, 0xac, 0x3c, 0x41, 0x22, - 0xbb, 0xc6, 0x1d, 0x7d, 0xa1, 0x75, 0x9d, 0x4e, 0x6d, 0xf7, 0x17, 0xbe, - 0xce, 0x35, 0x67, 0x53, 0xaa, 0x23, 0x69, 0x3a, 0x88, 0xfc, 0x52, 0x82, - 0x71, 0x2f, 0xd3, 0xa0, 0x55, 0xe7, 0x88, 0x6d, 0xc3, 0xae, 0xd3, 0x4e, - 0xaf, 0x4d, 0x30, 0x44, 0x2f, 0xed, 0x99, 0x6c, 0xff, 0xdd, 0x8e, 0xbd, - 0x19, 0xd3, 0xaf, 0x0e, 0x7c, 0xea, 0xe1, 0xb4, 0x11, 0xab, 0xcf, 0xbe, - 0x8e, 0xbe, 0x41, 0x6e, 0x1d, 0x7b, 0x68, 0x13, 0xa8, 0x07, 0xac, 0xb1, - 0xcf, 0x8f, 0xdf, 0xe5, 0x39, 0x9f, 0xe2, 0x7c, 0xeb, 0x93, 0xa7, 0x5f, - 0xdb, 0x78, 0xda, 0x23, 0x87, 0x52, 0xb4, 0x9c, 0x3b, 0xb5, 0x63, 0xb2, - 0x17, 0xf0, 0xce, 0x05, 0x6f, 0xfb, 0x00, 0x04, 0xdf, 0x37, 0xf9, 0xd7, - 0xd2, 0x17, 0x69, 0xd6, 0xdb, 0x87, 0xb3, 0x07, 0x37, 0xff, 0x01, 0xc1, - 0xd7, 0xfa, 0x49, 0x00, 0x75, 0xf3, 0x2e, 0xa9, 0xa7, 0x5f, 0xf3, 0x3a, - 0x9d, 0x03, 0xb0, 0x40, 0x75, 0xf6, 0x82, 0x2a, 0x1d, 0x7f, 0x70, 0x3b, - 0x33, 0xc4, 0x3a, 0xf8, 0x47, 0x3e, 0x75, 0x3a, 0x67, 0x40, 0x28, 0xc4, - 0x24, 0x24, 0x64, 0xf3, 0x84, 0x5f, 0x2f, 0xbf, 0xbc, 0x32, 0xff, 0x19, - 0xc7, 0x5f, 0xfe, 0x17, 0x9d, 0xd7, 0xee, 0x27, 0x1c, 0x07, 0x5e, 0x18, - 0x59, 0xd4, 0xd4, 0x49, 0xe1, 0x8a, 0x24, 0x5a, 0x65, 0x69, 0xd6, 0x80, - 0xcf, 0x87, 0xca, 0xd8, 0x71, 0xe5, 0x10, 0xed, 0x0e, 0xb6, 0x96, 0x82, - 0x54, 0xb6, 0x4e, 0x54, 0x29, 0x0b, 0xb9, 0x4a, 0x8d, 0xde, 0x34, 0xe4, - 0x8c, 0xc1, 0x99, 0x4a, 0x3d, 0x8c, 0x11, 0x70, 0xf7, 0xe4, 0xed, 0x24, - 0x47, 0x2f, 0xec, 0x6d, 0xd3, 0xf3, 0x70, 0xca, 0x51, 0xd4, 0xe1, 0xd7, - 0xe5, 0x8e, 0x31, 0x0a, 0x79, 0xe8, 0xea, 0x7c, 0xc7, 0xd8, 0xaa, 0x1e, - 0xd5, 0x33, 0xaf, 0x5b, 0xe5, 0xad, 0x51, 0xbf, 0xfd, 0x32, 0xe1, 0xb3, - 0x67, 0x65, 0x11, 0x23, 0x44, 0xd9, 0x7f, 0xa6, 0xce, 0xca, 0x22, 0x46, - 0x8a, 0xb6, 0xff, 0x35, 0xa1, 0xf8, 0xbb, 0x4e, 0xbe, 0xce, 0x47, 0xce, - 0xb4, 0xfb, 0x87, 0xa4, 0x26, 0x57, 0xfe, 0xe3, 0xf1, 0xf6, 0xeb, 0xe0, - 0x0e, 0xbf, 0x3f, 0x57, 0xc0, 0x1d, 0x7a, 0x22, 0x46, 0x8a, 0xd2, 0xfc, - 0xa6, 0xfa, 0x0e, 0xe7, 0x5b, 0xb2, 0x3d, 0x24, 0x27, 0xbf, 0xfe, 0x93, - 0xf7, 0x3d, 0x85, 0xc3, 0x5d, 0x24, 0x75, 0xff, 0xf3, 0x75, 0x82, 0xeb, - 0x8c, 0xff, 0xdd, 0x67, 0x5d, 0xff, 0xba, 0x26, 0x61, 0x36, 0xff, 0xff, - 0xf3, 0xce, 0x4f, 0xeb, 0x14, 0x97, 0x13, 0xf8, 0xc8, 0xba, 0xf6, 0xc6, - 0x0e, 0xbe, 0x6f, 0xd3, 0x63, 0xaf, 0xde, 0x7e, 0x2f, 0xe9, 0xd6, 0x7d, - 0xcf, 0x2e, 0x71, 0x15, 0xfb, 0x38, 0x98, 0xb3, 0xaf, 0xfe, 0x18, 0x49, - 0x72, 0x03, 0xb7, 0x50, 0xea, 0xd8, 0xf9, 0xf8, 0x4b, 0x7f, 0x9a, 0xfd, - 0xd9, 0xfb, 0xb1, 0xd7, 0xe6, 0x70, 0x0b, 0x57, 0x3a, 0xfe, 0x17, 0x63, - 0x76, 0xe8, 0xea, 0x64, 0xf6, 0x55, 0x15, 0xd3, 0xa2, 0xcb, 0x21, 0x1b, - 0x7f, 0x9b, 0x9f, 0x81, 0xf4, 0x27, 0x5a, 0x69, 0xfd, 0x71, 0x45, 0xca, - 0xf6, 0x3d, 0xc7, 0x94, 0x86, 0x07, 0x4b, 0x79, 0x0c, 0x58, 0x84, 0x88, - 0xc3, 0x57, 0xe4, 0xd7, 0xfa, 0x6c, 0xec, 0xa2, 0x24, 0x68, 0xb0, 0x2f, - 0xdd, 0x94, 0x44, 0x8d, 0x13, 0xad, 0xff, 0xfe, 0xe3, 0xec, 0x0c, 0x5c, - 0xda, 0xd6, 0x71, 0x34, 0x1d, 0x8e, 0xbf, 0x4c, 0xb8, 0x6c, 0xd8, 0x89, - 0x66, 0x4c, 0xef, 0xf3, 0x75, 0x32, 0x8a, 0x3a, 0xce, 0xbf, 0x76, 0x51, - 0x12, 0x34, 0x5b, 0x37, 0xff, 0xfa, 0x1b, 0x36, 0x9d, 0x30, 0x09, 0x9a, - 0xcf, 0x8b, 0x9d, 0x7f, 0xef, 0x5f, 0x53, 0x71, 0x25, 0x1d, 0x3a, 0xff, - 0x9d, 0xaf, 0xdd, 0x9f, 0xbb, 0x1d, 0x69, 0xb1, 0x30, 0x75, 0x99, 0xc2, - 0xe0, 0x9f, 0xdf, 0xff, 0xa3, 0xdf, 0x43, 0xa9, 0xb3, 0xb1, 0xae, 0x43, - 0x4e, 0xbe, 0x94, 0x44, 0x8d, 0x17, 0x35, 0x96, 0x75, 0x74, 0xde, 0xb0, - 0x5b, 0x73, 0x2b, 0x3a, 0xd3, 0x61, 0xb9, 0x60, 0x8a, 0xfd, 0xd9, 0x44, - 0x48, 0xd1, 0x77, 0xdf, 0xe6, 0xcd, 0xae, 0xf5, 0x18, 0x3a, 0xd3, 0x61, - 0xf4, 0x41, 0x9d, 0xf4, 0xca, 0x03, 0xd3, 0xa9, 0xdd, 0xce, 0xee, 0x5a, - 0xf8, 0x69, 0x1a, 0xee, 0xae, 0x93, 0x9c, 0x5d, 0x85, 0x52, 0xe1, 0xab, - 0x08, 0x5e, 0xc6, 0x7a, 0x28, 0x5a, 0x86, 0x6f, 0xe1, 0x21, 0xe4, 0x9e, - 0xfd, 0xad, 0x2e, 0x1a, 0x75, 0xda, 0x73, 0xaf, 0xfe, 0xde, 0x41, 0x8d, - 0xff, 0x98, 0x2a, 0x1d, 0x78, 0x62, 0x67, 0x44, 0x0e, 0x89, 0xfe, 0x2b, - 0x78, 0x30, 0xb3, 0xaf, 0xed, 0xb1, 0x57, 0xdd, 0x43, 0xab, 0xa7, 0x96, - 0x23, 0x77, 0xfe, 0xd4, 0x29, 0xc4, 0x71, 0x0b, 0x9d, 0x7f, 0xee, 0x47, - 0xe3, 0x9b, 0xb7, 0x3e, 0x75, 0x61, 0xfd, 0x21, 0xe5, 0xd1, 0xe9, 0xd7, - 0xff, 0xff, 0x86, 0x18, 0x1c, 0xff, 0xf3, 0x67, 0x18, 0x53, 0x4b, 0x7c, - 0x10, 0x1d, 0x58, 0x88, 0xae, 0x8b, 0x5f, 0xee, 0x60, 0x12, 0x77, 0x70, - 0xeb, 0xe9, 0x44, 0x48, 0xd1, 0x2b, 0xdf, 0xfe, 0xff, 0x31, 0xb2, 0xe2, - 0x01, 0xc7, 0xe7, 0x53, 0x51, 0x51, 0xd3, 0x31, 0x2d, 0xb9, 0xbb, 0x1d, - 0x7f, 0xe1, 0x86, 0x01, 0xc7, 0xdb, 0x18, 0x3a, 0xff, 0xfe, 0x6e, 0x27, - 0xb8, 0xb4, 0xfe, 0x9d, 0x71, 0xbf, 0xce, 0xbe, 0x0c, 0x75, 0xa7, 0x5f, - 0xf3, 0xc8, 0x5f, 0x6f, 0x63, 0xe7, 0x5f, 0xff, 0xe4, 0xfc, 0x2e, 0x07, - 0xde, 0x31, 0x03, 0xb4, 0x93, 0x63, 0xa8, 0x08, 0xba, 0x42, 0x18, 0x38, - 0xa0, 0x27, 0x03, 0x87, 0xfc, 0x8c, 0x52, 0xff, 0xdf, 0x86, 0xeb, 0x8f, - 0xdf, 0x20, 0x3a, 0xff, 0xef, 0xa4, 0xe4, 0xfb, 0x2d, 0x71, 0xf9, 0xd7, - 0xff, 0xa3, 0x1b, 0xcc, 0x41, 0xcf, 0x67, 0xb0, 0xeb, 0xd0, 0xd9, 0x9d, - 0x73, 0x69, 0xb0, 0x9b, 0x04, 0x2a, 0xb2, 0x19, 0x4b, 0x2f, 0xd4, 0x73, - 0x1f, 0x36, 0xf2, 0x80, 0xa9, 0x16, 0xff, 0xf6, 0x72, 0x61, 0xc0, 0x20, - 0xff, 0x38, 0x75, 0xef, 0xb8, 0x0a, 0xbf, 0xfd, 0xc8, 0x4f, 0xbb, 0x53, - 0xbb, 0x07, 0xd2, 0xaf, 0xf4, 0x4a, 0x60, 0x76, 0x7e, 0x99, 0xcf, 0x97, - 0x43, 0x76, 0x9a, 0x4b, 0xe1, 0x8b, 0x9d, 0x65, 0xfc, 0x2a, 0xa7, 0x42, - 0xb2, 0xff, 0xf4, 0xcb, 0x86, 0xcd, 0x9d, 0x94, 0x44, 0x8d, 0x13, 0x0d, - 0xff, 0xfd, 0x93, 0xa0, 0x1c, 0x79, 0xbf, 0xcc, 0x00, 0x7f, 0xa3, 0xaf, - 0xff, 0x76, 0x3d, 0x99, 0x4f, 0xb5, 0x87, 0xd3, 0x4e, 0xbb, 0x26, 0x14, - 0x55, 0xf9, 0x5d, 0xbf, 0xfa, 0x7d, 0xcd, 0xda, 0x18, 0xf8, 0xbb, 0x4e, - 0xbf, 0x62, 0xfc, 0x6e, 0xae, 0x75, 0xfc, 0xeb, 0xcf, 0x5e, 0x71, 0xd4, - 0x03, 0xdb, 0xe1, 0x6d, 0xfb, 0x8e, 0x04, 0x50, 0xea, 0x43, 0xc9, 0x54, - 0x45, 0x7f, 0x9e, 0x36, 0xfa, 0x91, 0xd3, 0xaf, 0xd1, 0xd6, 0xc2, 0xce, - 0xa1, 0x3d, 0x90, 0x99, 0xdf, 0xff, 0x93, 0xbc, 0x8f, 0x00, 0xc6, 0xf1, - 0xe7, 0x01, 0xce, 0xbf, 0xfb, 0x37, 0x63, 0xcf, 0x1e, 0x5c, 0x46, 0x4e, - 0xae, 0x22, 0x7c, 0x55, 0xef, 0xe5, 0xbe, 0x0f, 0xe7, 0x8e, 0xb6, 0x8e, - 0xbf, 0x3e, 0x0f, 0xe7, 0x8e, 0xbf, 0xb8, 0x9f, 0xd4, 0x6f, 0xe0, 0xf9, - 0x99, 0x2e, 0x58, 0x85, 0xfe, 0x6f, 0xdd, 0x73, 0xbd, 0x69, 0xd7, 0xff, - 0xf9, 0x85, 0x5f, 0xce, 0x78, 0x1c, 0xd9, 0x30, 0x77, 0x6e, 0x8e, 0xbf, - 0x31, 0xfc, 0xe4, 0x8e, 0xb0, 0xe2, 0x23, 0x61, 0x96, 0xff, 0xf7, 0xc6, - 0x3d, 0xe6, 0x20, 0x03, 0xfd, 0x1d, 0x7f, 0xcf, 0xb7, 0x96, 0xf0, 0x31, - 0xb1, 0xd4, 0xe8, 0x85, 0xea, 0x4d, 0xfd, 0x3b, 0xcf, 0xc5, 0xfd, 0x3a, - 0xff, 0xf3, 0xff, 0xd7, 0x6e, 0x6f, 0xfd, 0x82, 0xc1, 0xd4, 0xe7, 0xfc, - 0x86, 0x37, 0xfb, 0xd8, 0xf7, 0xbd, 0x4e, 0x9d, 0x7f, 0x69, 0x14, 0x5c, - 0x7c, 0xeb, 0xff, 0xff, 0x77, 0x27, 0x38, 0xff, 0xc7, 0x91, 0x7e, 0x42, - 0x7d, 0xff, 0xa3, 0xaf, 0xe1, 0xcd, 0x78, 0x94, 0xfe, 0x75, 0x6e, 0x8c, - 0xee, 0x96, 0xce, 0x6e, 0xbe, 0xf1, 0x39, 0x56, 0xc7, 0x56, 0x1e, 0xe2, - 0x86, 0x77, 0xff, 0xc1, 0x9f, 0x85, 0xd7, 0x09, 0xc8, 0xff, 0x1c, 0xeb, - 0xfc, 0xe3, 0xf8, 0x5a, 0x7c, 0xea, 0xc4, 0x40, 0xf1, 0x46, 0xff, 0xfd, - 0xc1, 0xcf, 0xf1, 0x33, 0x7f, 0xe4, 0xe7, 0xd1, 0xd7, 0xff, 0x40, 0xf1, - 0xd0, 0x09, 0xac, 0x69, 0xd7, 0x9f, 0xdf, 0x27, 0x56, 0x22, 0xce, 0x15, - 0x45, 0x02, 0xf7, 0x90, 0x61, 0xd7, 0xa7, 0xed, 0x4f, 0xe7, 0x54, 0x1e, - 0x1e, 0x87, 0x6f, 0xf0, 0xc3, 0x0f, 0xfc, 0xd8, 0xeb, 0x4d, 0x3f, 0xb2, - 0x33, 0x1e, 0x1d, 0x80, 0x7c, 0xc8, 0x60, 0x4a, 0x11, 0x1b, 0xaa, 0xb3, - 0x0c, 0x3e, 0xc2, 0xaf, 0x90, 0xa0, 0xf4, 0x80, 0x63, 0x5e, 0xd4, 0x28, - 0xff, 0x0d, 0x50, 0xb8, 0x4f, 0x10, 0xdf, 0xff, 0x75, 0x37, 0x6e, 0x93, - 0xfc, 0x7e, 0xfd, 0xce, 0xbf, 0x76, 0x51, 0x12, 0x34, 0x55, 0xd7, 0xba, - 0xeb, 0x3a, 0xff, 0x9b, 0x36, 0x76, 0x51, 0x12, 0x34, 0x47, 0x97, 0xfc, - 0xed, 0x7e, 0xec, 0xfd, 0xd8, 0xeb, 0x4c, 0x04, 0xc6, 0xf1, 0x3f, 0xa6, - 0x70, 0x36, 0x28, 0xb7, 0xee, 0xca, 0x22, 0x46, 0x8b, 0x06, 0xf2, 0x8f, - 0xb1, 0xd7, 0xff, 0xf0, 0x86, 0x36, 0x5e, 0x4f, 0x07, 0xb9, 0xd6, 0xf9, - 0x69, 0xd7, 0xec, 0x1c, 0xfe, 0x8e, 0xbf, 0xdd, 0x85, 0xf9, 0xec, 0x6e, - 0x75, 0xa6, 0xc4, 0xc2, 0x94, 0x33, 0x90, 0xec, 0x30, 0x79, 0x25, 0xbf, - 0xd3, 0x67, 0x65, 0x11, 0x23, 0x45, 0x95, 0x7e, 0xec, 0xa2, 0x24, 0x68, - 0xb4, 0xef, 0xfa, 0x01, 0xc8, 0x67, 0x88, 0xb3, 0xad, 0x36, 0x1f, 0x5a, - 0xcc, 0xef, 0xca, 0xd9, 0x5b, 0xd5, 0xa5, 0x6a, 0x7c, 0x3a, 0xff, 0xa7, - 0xfe, 0x23, 0x00, 0x88, 0x91, 0xd7, 0xe5, 0x6d, 0x3e, 0xeb, 0x1c, 0xeb, - 0xfd, 0xe5, 0x79, 0xfd, 0x26, 0x8e, 0xb2, 0x1d, 0x53, 0xf9, 0xe1, 0xcf, - 0x1a, 0x5f, 0xff, 0xc9, 0xc8, 0x1f, 0xb7, 0x3b, 0x8e, 0x23, 0x9f, 0x3a, - 0xfd, 0x3a, 0x01, 0x8b, 0x3a, 0xf9, 0x6f, 0xbe, 0x8e, 0xa6, 0xa2, 0x7f, - 0x15, 0x59, 0x28, 0xbf, 0xd9, 0xaf, 0x1d, 0xe8, 0x78, 0x75, 0xff, 0xf9, - 0xc6, 0x5c, 0x4e, 0x27, 0x5d, 0x96, 0x33, 0x87, 0x5f, 0x3f, 0x97, 0xe1, - 0xd7, 0xd2, 0x88, 0x91, 0xa2, 0xdc, 0xbf, 0xf6, 0x77, 0x07, 0xc7, 0x33, - 0x76, 0x0e, 0xbf, 0x0f, 0xb1, 0xbe, 0x8e, 0xa7, 0x3e, 0x88, 0x40, 0xad, - 0xd1, 0xaf, 0xd2, 0x2d, 0x42, 0x56, 0xff, 0x40, 0xfa, 0xc8, 0xba, 0xce, - 0xbc, 0xb1, 0x43, 0xac, 0x27, 0x5f, 0xf7, 0x03, 0x1a, 0xcc, 0x15, 0x0e, - 0xbf, 0x6a, 0x37, 0x80, 0x1d, 0x64, 0x01, 0xef, 0x7c, 0xde, 0x9d, 0x15, - 0xd8, 0x35, 0xc6, 0xdb, 0xfe, 0xcf, 0xfd, 0x36, 0x5b, 0x89, 0xd7, 0xfc, - 0xe2, 0x15, 0xbe, 0xbe, 0x87, 0x5f, 0x01, 0xf3, 0xa7, 0x5f, 0xbc, 0x6f, - 0xa4, 0x50, 0xeb, 0x46, 0xc7, 0x97, 0xb9, 0x05, 0xff, 0xcd, 0xce, 0x27, - 0x41, 0xc7, 0x19, 0x1d, 0x7f, 0xb7, 0x6b, 0x8f, 0xf3, 0xd3, 0xaf, 0xb5, - 0xea, 0x7c, 0xea, 0x84, 0x60, 0x68, 0xa4, 0x28, 0x5e, 0x4c, 0xef, 0xfe, - 0xfa, 0x7a, 0xed, 0x07, 0x1c, 0x64, 0x75, 0x1d, 0x78, 0x31, 0xf3, 0xae, - 0x0b, 0x9d, 0x4d, 0x36, 0x1f, 0x1b, 0xa3, 0xaf, 0xb7, 0x92, 0x74, 0xeb, - 0xce, 0xb9, 0xb1, 0x10, 0xfb, 0x9d, 0x2c, 0x87, 0xe1, 0x54, 0xe9, 0x8c, - 0xa4, 0x32, 0xaf, 0x0f, 0xe7, 0x8e, 0xbf, 0xe6, 0xcd, 0x9d, 0x94, 0x44, - 0x8d, 0x14, 0x3d, 0x21, 0xf1, 0xc0, 0xf5, 0xfb, 0xd7, 0x96, 0x2c, 0xeb, - 0xe7, 0x67, 0x00, 0x75, 0x9f, 0xa7, 0x91, 0xa2, 0x7b, 0xff, 0x40, 0x1c, - 0x1c, 0x41, 0x45, 0x9d, 0x7f, 0xf6, 0x9c, 0x59, 0xc1, 0xf6, 0x3f, 0x87, - 0x5f, 0xed, 0x06, 0x59, 0xf1, 0x73, 0xa9, 0x68, 0xae, 0xe1, 0xdf, 0xd0, - 0xaf, 0xfe, 0x0b, 0x79, 0x1d, 0xdf, 0xee, 0x9b, 0x1d, 0x7f, 0xce, 0xd7, - 0xee, 0xcf, 0xdd, 0x8e, 0xbf, 0x27, 0xf5, 0x08, 0x75, 0xff, 0x77, 0xde, - 0xc0, 0xff, 0x3d, 0x3a, 0xbd, 0x3d, 0xe0, 0x92, 0xdf, 0xfd, 0x21, 0x7f, - 0x8e, 0x4e, 0xce, 0xb4, 0xeb, 0xfc, 0x23, 0x1f, 0xf2, 0xf2, 0x3a, 0xf8, - 0x7d, 0xdb, 0xd3, 0xab, 0x0f, 0x59, 0x0c, 0xaf, 0xfc, 0x9b, 0xeb, 0xc7, - 0xfc, 0x03, 0x04, 0xeb, 0xf4, 0x6f, 0xaf, 0xa1, 0xd5, 0x89, 0x91, 0x72, - 0x13, 0x22, 0x41, 0xa4, 0x2b, 0xf4, 0x05, 0x47, 0xf2, 0x75, 0xfa, 0x7f, - 0xce, 0xbe, 0x8e, 0xa6, 0x4f, 0x50, 0x4a, 0x6f, 0xfa, 0x34, 0xec, 0xee, - 0xdc, 0x9c, 0x75, 0xff, 0xf8, 0x1c, 0x7f, 0x33, 0x7c, 0x63, 0xdd, 0x69, - 0xfd, 0x2a, 0xe0, 0x61, 0xd5, 0x87, 0xdc, 0x8b, 0x37, 0xfb, 0x91, 0xeb, - 0x22, 0xe0, 0x3a, 0xd3, 0x2b, 0x2c, 0xd2, 0xc9, 0xf1, 0x11, 0x5b, 0xcf, - 0x55, 0x8b, 0xa3, 0xc3, 0x25, 0xa6, 0x00, 0x35, 0xc8, 0xca, 0xd4, 0x36, - 0x94, 0x38, 0x37, 0x2e, 0x43, 0x76, 0x63, 0x41, 0xec, 0x6a, 0xeb, 0x84, - 0x57, 0x1a, 0x22, 0x1a, 0xbe, 0x98, 0x0a, 0x2e, 0xa1, 0x2f, 0xf8, 0xd1, - 0x43, 0x09, 0x59, 0xc4, 0x53, 0xd0, 0xa9, 0xf2, 0x41, 0x7f, 0xa6, 0xce, - 0xca, 0x22, 0x46, 0x8b, 0xce, 0x9d, 0xbe, 0x1b, 0x6a, 0xd8, 0x23, 0x02, - 0xca, 0x47, 0xe6, 0xf2, 0x8a, 0x3b, 0x1a, 0xca, 0xd4, 0xf9, 0x0a, 0xa1, - 0xa6, 0xaa, 0x4e, 0x8e, 0xc6, 0xff, 0x4d, 0x9d, 0x94, 0x44, 0x8d, 0x14, - 0xb5, 0xfb, 0xb2, 0x88, 0x91, 0xa2, 0xc2, 0xbf, 0xff, 0x3e, 0x08, 0x1f, - 0x8f, 0xbf, 0xf0, 0x61, 0x67, 0x5f, 0xc1, 0xea, 0x6d, 0x0b, 0x3a, 0xd3, - 0x62, 0x2c, 0x56, 0x67, 0x3c, 0xa3, 0x7f, 0xa6, 0xce, 0xca, 0x22, 0x46, - 0x8b, 0x2e, 0xee, 0xa8, 0x75, 0xf4, 0xca, 0x2b, 0x15, 0x64, 0xeb, 0xd3, - 0x79, 0x59, 0xd5, 0x23, 0xce, 0x09, 0x7d, 0x0a, 0x21, 0xf4, 0xcb, 0x6f, - 0x4e, 0xb9, 0x4d, 0x8e, 0xba, 0x3a, 0xd3, 0x53, 0x82, 0x37, 0xfd, 0x1b, - 0x8e, 0x6f, 0xf7, 0x50, 0xeb, 0xfd, 0xb6, 0xfa, 0x70, 0x7d, 0x0e, 0xbf, - 0x3e, 0x4e, 0x7d, 0x1d, 0x67, 0x83, 0xdb, 0x60, 0xd2, 0xa1, 0x17, 0x63, - 0x09, 0x4b, 0xe8, 0x6b, 0x40, 0x75, 0xfd, 0x1d, 0x7f, 0xc7, 0x0e, 0xbc, - 0xc3, 0x0c, 0x15, 0x7f, 0xce, 0xdd, 0xff, 0xd7, 0xcd, 0xca, 0x98, 0xbf, - 0xb9, 0xf4, 0x75, 0x01, 0x19, 0x3c, 0x21, 0x14, 0xa9, 0xc9, 0x37, 0xf2, - 0x46, 0xbd, 0xd0, 0x4e, 0xbf, 0xff, 0xb8, 0x9f, 0xe6, 0x68, 0x71, 0x61, - 0xd7, 0x21, 0xa7, 0x5f, 0xe7, 0x6f, 0xe3, 0x90, 0x03, 0xab, 0x11, 0x15, - 0xd5, 0x9b, 0x34, 0xeb, 0x34, 0xeb, 0x34, 0xea, 0x73, 0x60, 0xa0, 0x82, - 0x08, 0x5f, 0xff, 0xbf, 0xa4, 0x96, 0x0f, 0x5c, 0x70, 0x18, 0xa1, 0xd6, - 0xdc, 0xeb, 0xb4, 0x13, 0xab, 0x0f, 0xe7, 0x4a, 0x5f, 0x11, 0xb9, 0x1c, - 0xeb, 0xf8, 0x5d, 0x62, 0xf8, 0x75, 0xcd, 0x73, 0xa8, 0x07, 0xa4, 0xc8, - 0xa0, 0x4a, 0x6f, 0xff, 0xff, 0xb8, 0xff, 0xd2, 0x6b, 0x4f, 0xfe, 0x23, - 0xf7, 0xd5, 0xc3, 0x5b, 0xf5, 0x0e, 0xb9, 0x37, 0x3a, 0xe7, 0x59, 0xd7, - 0xff, 0xf3, 0x5c, 0x42, 0xd6, 0xbf, 0xf9, 0x8b, 0xf2, 0xfe, 0x9d, 0x74, - 0xa6, 0x75, 0xdc, 0x2d, 0x92, 0xc1, 0x0e, 0x6c, 0x87, 0x7c, 0x8f, 0xbb, - 0x0b, 0x78, 0x52, 0x18, 0x53, 0x6a, 0x10, 0x1f, 0x30, 0x9c, 0xfd, 0x3c, - 0x2d, 0xe4, 0x56, 0xff, 0xf4, 0xcb, 0x86, 0xcd, 0x9d, 0x94, 0x44, 0x8d, - 0x14, 0x65, 0xfa, 0x73, 0xf5, 0xfd, 0x3a, 0xfc, 0x31, 0xeb, 0xf9, 0x3a, - 0xff, 0xed, 0xe4, 0x9d, 0xe6, 0x60, 0xb7, 0x47, 0x5a, 0x67, 0x44, 0xa7, - 0x0a, 0x7e, 0x51, 0x4d, 0x64, 0xd8, 0xf6, 0x1e, 0x0b, 0x39, 0x89, 0xe8, - 0x8d, 0x43, 0x7f, 0xf0, 0xeb, 0xbf, 0xfa, 0x68, 0x6c, 0xd9, 0xd9, 0x44, - 0x48, 0xd1, 0x1c, 0xdf, 0xfe, 0x99, 0x70, 0xd9, 0xb3, 0xb2, 0x88, 0x91, - 0xa2, 0x72, 0xbf, 0xd3, 0x67, 0x65, 0x11, 0x23, 0x45, 0x99, 0x7f, 0xcd, - 0xd4, 0x2e, 0x6e, 0x7f, 0xd3, 0xaf, 0xf9, 0x58, 0x03, 0x16, 0xfb, 0xba, - 0xce, 0xbf, 0xef, 0x7a, 0xff, 0xe4, 0x6e, 0xd3, 0xaf, 0xf6, 0x6b, 0xbd, - 0xcd, 0xf4, 0x75, 0xdb, 0xac, 0xeb, 0x4c, 0xac, 0xa3, 0x09, 0xcf, 0x9a, - 0x75, 0x3c, 0x67, 0x7f, 0xa6, 0xce, 0xca, 0x22, 0x46, 0x8b, 0x76, 0xfe, - 0x18, 0x9b, 0xbb, 0x70, 0xeb, 0xc9, 0xbf, 0xa7, 0x5f, 0xfa, 0x1b, 0x36, - 0x76, 0x51, 0x12, 0x34, 0x52, 0x16, 0x9a, 0x48, 0x95, 0xe9, 0x72, 0xc7, - 0x6f, 0xfe, 0x9a, 0x1b, 0x36, 0x76, 0x51, 0x12, 0x34, 0x4a, 0x55, 0xb2, - 0xb8, 0xb6, 0x54, 0x56, 0xaf, 0x07, 0xfe, 0xc3, 0xf4, 0x52, 0xff, 0x0d, - 0x45, 0x46, 0xf7, 0xe9, 0x93, 0x41, 0x59, 0xd7, 0x86, 0x1a, 0x75, 0xff, - 0xa1, 0xb3, 0x67, 0x65, 0x11, 0x23, 0x44, 0xed, 0x76, 0xca, 0xe7, 0x5f, - 0xff, 0x90, 0x01, 0x5b, 0xaa, 0x80, 0x0b, 0x8e, 0x48, 0xeb, 0xfe, 0x76, - 0xbf, 0x76, 0x7e, 0xec, 0x75, 0xa6, 0xc4, 0xc2, 0x96, 0x35, 0xc4, 0xa8, - 0x1a, 0x15, 0x3b, 0xff, 0xe9, 0xbc, 0xcf, 0x40, 0xfb, 0x9f, 0x71, 0x4f, - 0x4e, 0xbf, 0xfa, 0x17, 0xcc, 0x94, 0x71, 0xfc, 0xb4, 0xeb, 0xff, 0x87, - 0x39, 0x1b, 0x66, 0x86, 0x37, 0x3a, 0xe9, 0xe9, 0x80, 0x88, 0x6d, 0x22, - 0x53, 0x55, 0x47, 0x2e, 0x33, 0x2d, 0x27, 0xcf, 0x43, 0x6a, 0xff, 0xfe, - 0x04, 0x7e, 0x6c, 0xd3, 0x8e, 0xfe, 0xeb, 0x4f, 0xe9, 0xd7, 0xee, 0xca, - 0x22, 0x46, 0x88, 0xb2, 0xff, 0xd0, 0xd9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, - 0x5d, 0xbf, 0xff, 0xb0, 0x1c, 0x7f, 0x33, 0x7c, 0x63, 0xdd, 0x69, 0xfd, - 0x2a, 0xd3, 0x62, 0x36, 0xd6, 0x67, 0x3c, 0x95, 0x7f, 0xfa, 0x65, 0xc3, - 0x66, 0xce, 0xca, 0x22, 0x46, 0x89, 0x8a, 0xfd, 0xd9, 0x44, 0x48, 0xd1, - 0x54, 0xdb, 0x0e, 0xac, 0x3c, 0x25, 0x0c, 0xef, 0xff, 0xff, 0x76, 0x39, - 0xbb, 0x73, 0xf3, 0x72, 0x35, 0xd4, 0x63, 0xfc, 0x4e, 0xb4, 0xea, 0x99, - 0x13, 0x90, 0x45, 0x7f, 0xfa, 0x65, 0xc3, 0x66, 0xce, 0xca, 0x22, 0x46, - 0x89, 0xd2, 0xff, 0x24, 0x75, 0xdb, 0x13, 0x8e, 0xbf, 0x32, 0xec, 0xbe, - 0x8e, 0xbf, 0x98, 0xc4, 0x9d, 0x82, 0x75, 0x21, 0xea, 0xe8, 0xa2, 0xf2, - 0x71, 0xce, 0x98, 0xd0, 0xdf, 0xfc, 0x1d, 0x7d, 0xf7, 0x98, 0x2c, 0xa2, - 0xce, 0xa5, 0x9f, 0x97, 0x0a, 0xef, 0xfd, 0x0d, 0x9b, 0x3b, 0x28, 0x89, - 0x1a, 0x27, 0x7b, 0xf7, 0xc3, 0x0b, 0x42, 0xaf, 0xfc, 0x2f, 0xfc, 0xd6, - 0x66, 0xed, 0x3a, 0x80, 0x9f, 0x46, 0x46, 0x34, 0xb2, 0x28, 0x4a, 0xf9, - 0x35, 0xfc, 0xf3, 0x7a, 0x38, 0x03, 0xaa, 0x63, 0xfc, 0x14, 0xfb, 0xff, - 0xd3, 0x2e, 0x1b, 0x36, 0x76, 0x51, 0x12, 0x34, 0x50, 0xb7, 0xff, 0xff, - 0xb8, 0x15, 0xae, 0x1b, 0x34, 0xb8, 0x1f, 0xb8, 0xe6, 0xca, 0x05, 0xd9, - 0x3a, 0xfc, 0x1d, 0xfe, 0x92, 0x3a, 0xfd, 0x9e, 0xe4, 0x09, 0xd7, 0x9f, - 0xd9, 0xb6, 0x3c, 0xd1, 0x28, 0xa4, 0x47, 0xe8, 0xc3, 0x22, 0xff, 0xf4, - 0xcb, 0x86, 0xcd, 0x9d, 0x94, 0x44, 0x8d, 0x14, 0x95, 0xff, 0xfe, 0xcd, - 0x4d, 0xe7, 0x19, 0xe4, 0x2f, 0xfc, 0x7f, 0x85, 0x67, 0x53, 0xaf, 0xed, - 0xed, 0x19, 0xc3, 0x4e, 0x65, 0x19, 0xaf, 0x48, 0xd7, 0x2a, 0xef, 0xd2, - 0x2f, 0xc6, 0xa8, 0x12, 0x69, 0xe5, 0x7b, 0xfd, 0x36, 0x76, 0x51, 0x12, - 0x34, 0x44, 0x97, 0xff, 0xa6, 0x5c, 0x36, 0x6c, 0xec, 0xa2, 0x24, 0x68, - 0x97, 0xaf, 0xba, 0x1f, 0xe8, 0xeb, 0xf7, 0x7d, 0x5a, 0x68, 0xeb, 0xfc, - 0x83, 0xff, 0x2b, 0x17, 0x3a, 0xff, 0xf7, 0x27, 0x38, 0xfa, 0xaf, 0x80, - 0xce, 0xee, 0x75, 0xcf, 0xf3, 0xaf, 0xff, 0x04, 0x09, 0xdf, 0x2c, 0xaa, - 0x0c, 0x0b, 0x27, 0x53, 0x51, 0xca, 0x86, 0x5e, 0xa7, 0xe8, 0x56, 0xff, - 0xe8, 0x67, 0x4f, 0x3a, 0x38, 0xfb, 0xb2, 0x75, 0xff, 0xcc, 0xf8, 0xf2, - 0x2f, 0x3a, 0x27, 0x3b, 0x27, 0x51, 0xd7, 0xf3, 0x2d, 0x8f, 0xc4, 0xe3, - 0xa9, 0xd1, 0x0b, 0x89, 0x90, 0x15, 0x77, 0x5c, 0xea, 0x02, 0xa7, 0xa4, - 0x22, 0x66, 0x30, 0xde, 0x9e, 0xce, 0x86, 0x62, 0xa2, 0xdb, 0xfe, 0x48, - 0x10, 0xfd, 0x97, 0x50, 0xeb, 0xff, 0xe4, 0xef, 0x8e, 0x3a, 0x7f, 0x41, - 0x90, 0x5c, 0xeb, 0xe4, 0xdb, 0xd5, 0x73, 0xaf, 0xa5, 0x11, 0x23, 0x45, - 0x2f, 0x4a, 0x22, 0x8d, 0x95, 0x0e, 0x93, 0x5f, 0x87, 0xfb, 0x63, 0x07, - 0x5f, 0xf9, 0xc5, 0xf9, 0xe0, 0x22, 0x19, 0x1d, 0x78, 0x31, 0xa3, 0xaf, - 0xb5, 0x9f, 0xd1, 0xd4, 0x03, 0xfa, 0x64, 0xfb, 0xe3, 0x77, 0xfd, 0xee, - 0xba, 0xfb, 0xb5, 0x16, 0x75, 0xef, 0xc4, 0xe3, 0xaf, 0xfa, 0x36, 0xf1, - 0xb0, 0x59, 0x75, 0x73, 0xa9, 0xd1, 0x2f, 0x07, 0x41, 0x1d, 0xbf, 0xe4, - 0xd3, 0x28, 0x3f, 0x7f, 0x4e, 0xa6, 0x9f, 0x32, 0xcb, 0xae, 0x81, 0x3a, - 0xff, 0x9f, 0xdf, 0x1c, 0x75, 0xc0, 0x9d, 0x6e, 0xee, 0x79, 0xb3, 0x85, - 0x2b, 0x11, 0x34, 0x8d, 0xf7, 0xba, 0xeb, 0x3a, 0xfe, 0x71, 0x67, 0xe8, - 0xa1, 0xd7, 0xf7, 0x7d, 0x79, 0x62, 0xce, 0xb9, 0xb8, 0x75, 0xe7, 0xf7, - 0x47, 0x53, 0x9e, 0xf0, 0x0b, 0x58, 0x15, 0xbf, 0x70, 0x2a, 0x60, 0x9d, - 0x7f, 0xcf, 0xcd, 0x47, 0xdf, 0xaa, 0x8e, 0xbf, 0xf2, 0xe0, 0x1e, 0x59, - 0x6b, 0x8e, 0xe7, 0x50, 0x0f, 0xe9, 0x0e, 0x6f, 0xbb, 0xef, 0x99, 0xc7, - 0x5e, 0x46, 0x3e, 0x75, 0x70, 0xf0, 0xf4, 0x4f, 0x40, 0x4c, 0x9f, 0x90, - 0xa1, 0xfb, 0x25, 0xff, 0xf9, 0xda, 0x2f, 0xb7, 0x96, 0x75, 0xcc, 0x55, - 0xdf, 0x4e, 0xbf, 0xbc, 0x2f, 0x3f, 0x1f, 0x3a, 0xd2, 0x3a, 0xed, 0xf5, - 0x86, 0xfa, 0x0b, 0xa9, 0x68, 0xc5, 0x88, 0x4c, 0xdf, 0xec, 0x61, 0xa9, - 0xa0, 0xac, 0xeb, 0xa7, 0x68, 0xeb, 0xf6, 0x6d, 0x9c, 0xd1, 0xd4, 0xe6, - 0xfc, 0x46, 0x2f, 0x67, 0x74, 0x75, 0x48, 0xdd, 0x4e, 0x1f, 0xbf, 0xef, - 0x5f, 0xdf, 0x33, 0x9c, 0x55, 0x1d, 0x4e, 0x98, 0x76, 0x42, 0xb1, 0x08, - 0xef, 0xff, 0xfe, 0xe3, 0xf7, 0x79, 0x26, 0xfe, 0x14, 0x8f, 0x1a, 0xe4, - 0x49, 0xc4, 0x07, 0x5f, 0xe1, 0x78, 0x1f, 0xe0, 0x9d, 0x7f, 0xb9, 0x0c, - 0xa7, 0x5f, 0x63, 0xae, 0xc5, 0x9d, 0x40, 0x47, 0x6a, 0xdd, 0xe0, 0xba, - 0x71, 0x9d, 0xf9, 0x52, 0x2d, 0xf4, 0x75, 0xfa, 0x27, 0x67, 0x74, 0x75, - 0x00, 0xf4, 0x16, 0x51, 0x7e, 0xe4, 0x0a, 0x2c, 0xea, 0x73, 0xc7, 0xc2, - 0x2b, 0xbd, 0x91, 0xd6, 0xd1, 0xd7, 0x22, 0x9a, 0x34, 0xe1, 0x17, 0xbe, - 0x7f, 0x62, 0x47, 0x5a, 0x67, 0x65, 0x5a, 0x81, 0xa3, 0x21, 0xb7, 0xb9, - 0x92, 0x42, 0x89, 0x98, 0xf1, 0xfa, 0x42, 0xb1, 0xbe, 0x42, 0x2e, 0x23, - 0x56, 0xf6, 0x1f, 0x63, 0x19, 0xae, 0xa3, 0x20, 0xfc, 0x35, 0x67, 0x91, - 0xfc, 0x96, 0xdf, 0xe9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x9c, 0xbf, 0xf2, - 0x76, 0x35, 0xcc, 0xc1, 0x91, 0xd7, 0xff, 0xee, 0x07, 0xfd, 0x7f, 0xeb, - 0x25, 0xa7, 0xec, 0x8e, 0xbf, 0xc8, 0xb0, 0x3e, 0x82, 0x27, 0x5f, 0xd9, - 0xfd, 0xda, 0xec, 0x1d, 0x7f, 0xf2, 0x89, 0xbe, 0x87, 0x01, 0xc8, 0x60, - 0xeb, 0xff, 0x67, 0x1f, 0xb9, 0x33, 0x0c, 0x30, 0x55, 0xc8, 0xc1, 0xd7, - 0x6d, 0x30, 0x13, 0x8b, 0x91, 0xdf, 0x15, 0x44, 0xc7, 0xe5, 0xd3, 0xc8, - 0xaa, 0x90, 0x6f, 0xdd, 0x94, 0x44, 0x8d, 0x15, 0xe5, 0xff, 0xfd, 0x80, - 0xe3, 0xf9, 0x9b, 0xe3, 0x1e, 0xeb, 0x4f, 0xe9, 0x56, 0x9b, 0x11, 0x23, - 0x3c, 0x67, 0x7f, 0xf4, 0xd0, 0xd9, 0xb3, 0xb2, 0x88, 0x91, 0xa2, 0x47, - 0xbd, 0x2c, 0x59, 0xd7, 0x93, 0xd7, 0x3a, 0xf4, 0xb1, 0x65, 0x4c, 0x5d, - 0xdf, 0xbb, 0x28, 0x89, 0x1a, 0x24, 0x8b, 0xff, 0xf9, 0xd3, 0xa8, 0xa9, - 0xc7, 0x67, 0xfa, 0x72, 0x36, 0x3a, 0xe6, 0xcc, 0xe8, 0xb8, 0xc2, 0xbe, - 0x19, 0xdf, 0xb3, 0x93, 0x62, 0xce, 0xb4, 0xce, 0x9a, 0x84, 0x43, 0xbb, - 0xe7, 0x77, 0xff, 0x4d, 0x0d, 0x9b, 0x3b, 0x28, 0x89, 0x1a, 0x24, 0xab, - 0xf7, 0x65, 0x11, 0x23, 0x45, 0xe3, 0x7e, 0xd6, 0xbf, 0x92, 0x3a, 0xff, - 0x9b, 0x36, 0x76, 0x51, 0x12, 0x34, 0x49, 0xb6, 0x9b, 0x11, 0x3f, 0xd3, - 0x38, 0x27, 0xb9, 0x8e, 0x1d, 0x7f, 0xfe, 0xd0, 0x63, 0x7c, 0xc5, 0x14, - 0x86, 0xe6, 0xff, 0x3a, 0xf3, 0x23, 0xb1, 0xd7, 0x7a, 0x27, 0x5d, 0x3d, - 0x33, 0xa2, 0x87, 0x05, 0xf4, 0xaf, 0xe4, 0x76, 0x9d, 0xb5, 0xca, 0xd8, - 0xfd, 0xb4, 0xd8, 0x60, 0x46, 0x30, 0x91, 0xe5, 0x33, 0x18, 0x42, 0xcb, - 0x39, 0x1d, 0x0f, 0xce, 0xc3, 0x0f, 0x0f, 0x30, 0xd6, 0xa7, 0x96, 0x6a, - 0xf7, 0xb4, 0xa4, 0x56, 0xce, 0x35, 0x82, 0x5c, 0xbe, 0x5f, 0xaf, 0x82, - 0x92, 0xd1, 0xa5, 0x78, 0x34, 0xfb, 0xd3, 0x6a, 0xd2, 0x91, 0xde, 0xaf, - 0x28, 0x75, 0x9b, 0x4f, 0x33, 0xda, 0xf1, 0x89, 0x79, 0x90, 0x6e, 0xf2, - 0x92, 0xa3, 0x16, 0xa4, 0xf7, 0xd9, 0xd9, 0xe9, 0xfa, 0x36, 0x11, 0xa6, - 0xa8, 0x6a, 0xb2, 0xf9, 0xfd, 0xe0, 0xc2, 0x06, 0xd3, 0x46, 0x4e, 0xa5, - 0x38, 0xb1, 0x2f, 0xf2, 0x7a, 0x58, 0x77, 0x9a, 0x41, 0x42, 0xaa, 0xd9, - 0xd6, 0x80, + 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x22, 0x5b, 0xbf, 0x01, 0xd7, 0xa4, + 0x2a, 0xe7, 0x5d, 0xbf, 0x8e, 0xbf, 0xfe, 0x8e, 0xc4, 0x85, 0xd4, 0xde, + 0x51, 0x9e, 0x3a, 0xe7, 0xd1, 0xd5, 0x23, 0xfa, 0x08, 0xba, 0x27, 0x5f, + 0xec, 0x64, 0x63, 0xdd, 0x43, 0xaf, 0xff, 0x68, 0x0b, 0xe8, 0xe6, 0xfe, + 0x17, 0xe9, 0xd7, 0x66, 0x8e, 0xbc, 0xee, 0xd3, 0x44, 0x5b, 0x52, 0x44, + 0x2e, 0x24, 0xb4, 0x56, 0xee, 0x68, 0xea, 0xe1, 0xe2, 0xe8, 0xbe, 0xff, + 0xfc, 0x07, 0xee, 0x0f, 0x39, 0x9b, 0xcb, 0xc8, 0xb3, 0xaf, 0x63, 0x60, + 0xeb, 0xf8, 0x23, 0x0d, 0x58, 0x0e, 0xbf, 0xe6, 0x45, 0x34, 0x83, 0xbc, + 0x8e, 0xbc, 0x14, 0x9c, 0xea, 0x43, 0xd4, 0x73, 0x8b, 0xff, 0x9b, 0xc8, + 0x52, 0x07, 0xca, 0xb2, 0xac, 0xac, 0x1d, 0x7f, 0x93, 0xa2, 0x07, 0x51, + 0xa7, 0x54, 0x22, 0x17, 0x14, 0xef, 0xff, 0x20, 0x8c, 0x6f, 0xf7, 0x39, + 0xac, 0x64, 0xeb, 0xb3, 0x72, 0xad, 0x05, 0x5b, 0xfe, 0x1a, 0x5f, 0xc5, + 0xaf, 0xf7, 0xb3, 0x9f, 0xad, 0x34, 0x53, 0x06, 0xa6, 0xfe, 0x97, 0x53, + 0x66, 0x4c, 0x75, 0x41, 0xf9, 0xba, 0x25, 0xfd, 0xd4, 0x6c, 0x2d, 0x0e, + 0xbf, 0xd1, 0xfc, 0xef, 0x28, 0x57, 0x3a, 0xc3, 0x07, 0xc2, 0x25, 0x76, + 0x61, 0x58, 0x5d, 0x5f, 0x55, 0xc2, 0xf1, 0x09, 0x89, 0xcb, 0xb2, 0x1f, + 0x6a, 0x11, 0x35, 0x51, 0x06, 0xbb, 0x08, 0x01, 0x85, 0x2e, 0x88, 0x76, + 0xe3, 0x0b, 0xfb, 0x08, 0x1b, 0xff, 0xff, 0x9d, 0x6c, 0x27, 0x38, 0x0e, + 0x72, 0x07, 0x14, 0x4e, 0xf7, 0x3e, 0x9d, 0x7f, 0xf9, 0x56, 0x51, 0x95, + 0x79, 0xc2, 0xaa, 0xf9, 0xf3, 0xbb, 0x67, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, + 0x2a, 0x2b, 0xf4, 0x77, 0x39, 0x87, 0x5f, 0xff, 0xbf, 0x94, 0xea, 0xb4, + 0x2b, 0x73, 0xb7, 0x9f, 0x3e, 0x77, 0x6c, 0xeb, 0xff, 0xf3, 0xc8, 0x63, + 0x59, 0xbb, 0x45, 0xf3, 0x76, 0x9d, 0x66, 0x24, 0x9b, 0xc6, 0x31, 0x34, + 0xcf, 0xa4, 0xbb, 0x1a, 0xef, 0xfc, 0x1c, 0x5b, 0x1b, 0x78, 0x29, 0xe3, + 0xaf, 0x63, 0x38, 0x75, 0xfe, 0xcc, 0x9c, 0x31, 0x81, 0x3a, 0xf7, 0x60, + 0x27, 0x5f, 0xe8, 0x84, 0x11, 0x02, 0xb9, 0xd7, 0x38, 0x0e, 0xbe, 0xea, + 0x75, 0x85, 0x42, 0x2b, 0x94, 0x1b, 0x98, 0xc7, 0xa3, 0x6c, 0x99, 0x5f, + 0xb8, 0xd7, 0x76, 0x9a, 0x2b, 0xdb, 0xf2, 0x6d, 0x34, 0x13, 0x9d, 0x74, + 0x48, 0xeb, 0xa3, 0xf3, 0xac, 0xc6, 0x22, 0x27, 0x86, 0x6e, 0x57, 0xf8, + 0xad, 0xff, 0xcc, 0x3c, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, 0x1a, 0xff, + 0xf3, 0x0b, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x13, 0xc5, 0xff, 0xe6, + 0x16, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x27, 0xfb, 0xff, 0xcc, 0x2d, + 0xe4, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x50, 0xd7, 0xff, 0x2d, 0xe4, 0xc6, + 0x71, 0xae, 0xed, 0x34, 0x51, 0x17, 0xfe, 0x93, 0x00, 0xd7, 0xc8, 0xd4, + 0x48, 0xea, 0x61, 0x12, 0x30, 0xa1, 0x7f, 0xe9, 0x93, 0xbb, 0xe7, 0x83, + 0x8b, 0x3a, 0xff, 0xc2, 0xec, 0x78, 0x40, 0xf2, 0xd1, 0xd7, 0xee, 0x35, + 0xdd, 0xa6, 0x8a, 0x46, 0xff, 0xa2, 0x51, 0xc9, 0xe3, 0x93, 0x9d, 0x79, + 0xe4, 0xc6, 0x1f, 0x60, 0x99, 0xdf, 0xd2, 0xce, 0xf5, 0xe4, 0x75, 0xff, + 0xfd, 0x81, 0xec, 0x7d, 0x63, 0xc2, 0xff, 0xeb, 0x51, 0xf9, 0x56, 0x62, + 0x13, 0xa4, 0x69, 0xfa, 0xe1, 0x53, 0xe3, 0x2d, 0xb2, 0xcb, 0xf7, 0x1a, + 0xee, 0xd3, 0x44, 0xa1, 0x7f, 0xf8, 0x5f, 0xda, 0xfa, 0x20, 0x90, 0xe2, + 0xce, 0xbe, 0x61, 0xe4, 0xc6, 0x1f, 0xe2, 0xcc, 0xea, 0x76, 0x7d, 0x2c, + 0xa7, 0x67, 0x83, 0x0e, 0x96, 0xc7, 0xd6, 0x8a, 0x6a, 0xf0, 0xee, 0xe4, + 0x3c, 0x96, 0x87, 0xd5, 0x1f, 0xd5, 0xd5, 0x2a, 0xfa, 0x87, 0x40, 0x23, + 0xc7, 0xda, 0x86, 0xad, 0xff, 0xe6, 0x16, 0xf2, 0x63, 0x38, 0xd7, 0x76, + 0x9a, 0x27, 0x3b, 0xff, 0xcc, 0x2d, 0xe4, 0xc6, 0x71, 0xae, 0xed, 0x34, + 0x51, 0x37, 0xf2, 0x6a, 0x69, 0x27, 0xe7, 0x5f, 0xe8, 0x9f, 0xee, 0xdb, + 0x8f, 0xe7, 0x5e, 0xe4, 0x98, 0xe9, 0xf3, 0x7d, 0x2e, 0xae, 0x26, 0x97, + 0xa5, 0x70, 0x42, 0xf6, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x0e, 0x5f, 0xc0, + 0x6f, 0x12, 0x04, 0xeb, 0x31, 0x87, 0xbd, 0xd3, 0x3b, 0xfe, 0x8e, 0x63, + 0x7b, 0x1b, 0xc8, 0xeb, 0xe6, 0xbb, 0xb4, 0xd1, 0x17, 0xdf, 0xb2, 0x69, + 0x3e, 0x8e, 0xae, 0x1e, 0xa7, 0xd2, 0xdb, 0xfd, 0xac, 0x0f, 0x73, 0xf7, + 0x3a, 0xe1, 0x9c, 0xeb, 0xfe, 0xf0, 0xc2, 0xfe, 0x87, 0xb0, 0x75, 0x41, + 0xe7, 0xa0, 0xb5, 0xda, 0xdc, 0xeb, 0xef, 0x4a, 0x14, 0x2a, 0x96, 0x6e, + 0x5c, 0x5e, 0xfc, 0xf3, 0xfb, 0x3a, 0x75, 0x98, 0x9d, 0x3d, 0x1c, 0x84, + 0x64, 0xc4, 0x9d, 0x84, 0x08, 0xac, 0xed, 0x90, 0x5f, 0xff, 0xff, 0x0b, + 0xb1, 0x80, 0x54, 0xa2, 0x89, 0xee, 0xe2, 0x4b, 0x5f, 0x31, 0x48, 0x91, + 0xd7, 0xfe, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x13, 0x25, 0x98, 0x6a, + 0x33, 0x17, 0x08, 0x2b, 0xba, 0xb3, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x16, + 0xf5, 0x98, 0x09, 0xe4, 0xe0, 0xb5, 0xff, 0xe6, 0x16, 0xf2, 0x63, 0x38, + 0xd7, 0x76, 0x9a, 0x29, 0x3b, 0x95, 0x95, 0x6c, 0xeb, 0xfb, 0x3c, 0x31, + 0x0b, 0x3a, 0xfe, 0xdf, 0xff, 0xbc, 0x7f, 0xce, 0xbb, 0xac, 0x2a, 0x0f, + 0xf3, 0xa4, 0x0e, 0x55, 0x50, 0xb9, 0xc7, 0x28, 0xfe, 0x72, 0x33, 0x8d, + 0x3c, 0x6c, 0x28, 0xfb, 0x0d, 0x3b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, + 0x43, 0xb7, 0xee, 0x35, 0xdd, 0xa6, 0x89, 0x62, 0xfb, 0x3f, 0x5a, 0x1d, + 0x7e, 0x61, 0x6f, 0x26, 0x30, 0xf5, 0x36, 0xcc, 0xef, 0xf3, 0x19, 0xc6, + 0xbb, 0xb4, 0xd1, 0x18, 0x5f, 0x31, 0x2c, 0xd1, 0xd7, 0xff, 0xfd, 0x2d, + 0x30, 0xde, 0xbc, 0xcd, 0xee, 0x71, 0x58, 0xec, 0xcb, 0xd1, 0xd7, 0xec, + 0xf7, 0xf0, 0xd3, 0xaf, 0xff, 0x47, 0x93, 0xf8, 0x90, 0x7b, 0x02, 0xd3, + 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x11, 0xed, 0xf6, 0x9f, 0x7d, 0x87, 0x5d, + 0x26, 0x30, 0xf5, 0xfc, 0x67, 0x7f, 0xff, 0x3b, 0x02, 0x0c, 0xee, 0x0f, + 0xf8, 0x3e, 0xee, 0x1d, 0x66, 0x37, 0x4e, 0xf2, 0x67, 0x0e, 0x13, 0xbc, + 0x27, 0xc4, 0xba, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x61, 0xdf, 0xe9, 0x0c, + 0x66, 0xb0, 0x4e, 0xb3, 0x18, 0x7c, 0x5b, 0x99, 0xdf, 0xe6, 0x33, 0x8d, + 0x77, 0x69, 0xa2, 0xe7, 0xbf, 0xff, 0xff, 0xfa, 0x15, 0xa4, 0xa7, 0x6f, + 0x7e, 0x7c, 0xee, 0xdb, 0x13, 0x81, 0x45, 0x5d, 0x0a, 0x8d, 0xe7, 0x9d, + 0xab, 0xf9, 0xf3, 0xbb, 0x67, 0x54, 0x2e, 0x6e, 0xcf, 0x09, 0x39, 0x21, + 0xb4, 0xfd, 0x23, 0xde, 0x5c, 0x2e, 0x7c, 0x53, 0xb4, 0x7f, 0x7f, 0x98, + 0xce, 0x35, 0xdd, 0xa6, 0x88, 0x7a, 0xf9, 0xae, 0xed, 0x34, 0x44, 0xd7, + 0xf6, 0x6d, 0x01, 0x78, 0x13, 0xaf, 0xf7, 0x80, 0xfb, 0xf6, 0x36, 0x1d, + 0x5c, 0x44, 0x88, 0x96, 0xf8, 0xbe, 0xfe, 0x4f, 0xf5, 0xf3, 0x02, 0x75, + 0xff, 0xfa, 0x39, 0xff, 0x63, 0x64, 0xd1, 0x0b, 0xd6, 0x04, 0xeb, 0xfe, + 0xef, 0x63, 0x64, 0xb3, 0x90, 0x75, 0xbd, 0xd4, 0x48, 0x3a, 0xbd, 0xff, + 0x27, 0x93, 0xd9, 0xfc, 0x70, 0xea, 0xc3, 0xdf, 0x72, 0x8b, 0xff, 0xfb, + 0xdd, 0x8e, 0x7f, 0xac, 0x0f, 0x80, 0xed, 0xce, 0x1d, 0x77, 0x96, 0x75, + 0xff, 0xec, 0xef, 0xd9, 0xf5, 0x09, 0xbf, 0xa1, 0x67, 0x5f, 0xfa, 0x78, + 0x97, 0xdc, 0xe6, 0xb1, 0x93, 0xab, 0x11, 0xfd, 0xba, 0xdf, 0x45, 0x80, + 0x99, 0x7d, 0xe0, 0x3f, 0xd3, 0x44, 0x2f, 0x7e, 0xee, 0x4e, 0x01, 0x3a, + 0xf9, 0xf9, 0x1b, 0x0e, 0xa0, 0x9e, 0x4f, 0xe4, 0xf6, 0x63, 0x15, 0xa2, + 0x70, 0xbf, 0xb1, 0x8f, 0x6a, 0x31, 0xe0, 0x1e, 0xec, 0x79, 0xbf, 0xf7, + 0x01, 0x3e, 0x76, 0x61, 0x80, 0x9d, 0x77, 0x5c, 0xeb, 0x00, 0xea, 0xc3, + 0x4b, 0xa1, 0x5b, 0xdf, 0xe9, 0x88, 0x44, 0x27, 0x99, 0x2f, 0xff, 0xb1, + 0x25, 0xa6, 0x33, 0x79, 0x3c, 0xff, 0x5a, 0x75, 0x42, 0x22, 0x7a, 0x6d, + 0x7e, 0x56, 0x34, 0x93, 0xaa, 0x0e, 0xbf, 0x95, 0x9f, 0xbd, 0xee, 0x4e, + 0x75, 0xba, 0x75, 0x2b, 0x27, 0x8a, 0x03, 0x5b, 0xe0, 0xe0, 0xcc, 0x75, + 0xc9, 0xe3, 0xad, 0xe4, 0x36, 0xdd, 0x21, 0xbf, 0xdb, 0xfb, 0x79, 0x00, + 0x54, 0x3a, 0xff, 0xd1, 0x30, 0xe6, 0xc7, 0x5a, 0xd0, 0xea, 0x73, 0xf4, + 0x01, 0xb5, 0xff, 0xff, 0xdd, 0x00, 0x53, 0x39, 0x30, 0xe6, 0xce, 0xe0, + 0x63, 0x5a, 0x85, 0x0e, 0xbf, 0xfc, 0x93, 0x4b, 0x37, 0x97, 0xc5, 0xbb, + 0x89, 0xd7, 0x3e, 0xd1, 0xd6, 0x54, 0x62, 0x72, 0x2a, 0x42, 0x69, 0xa4, + 0x3d, 0x73, 0x74, 0xbb, 0xb6, 0xd4, 0x3a, 0xfd, 0xd7, 0xf3, 0xc8, 0xeb, + 0xf9, 0x38, 0x39, 0x9c, 0x3a, 0xff, 0x4b, 0x51, 0xa5, 0x6a, 0xac, 0xab, + 0x27, 0x5f, 0xfc, 0xbf, 0x9a, 0x1c, 0xde, 0x42, 0xf3, 0x9d, 0x7b, 0x49, + 0xf9, 0xd5, 0x87, 0xc4, 0x88, 0xd7, 0x99, 0x65, 0x92, 0xaf, 0xce, 0x3e, + 0xee, 0x14, 0xc1, 0x7f, 0x7e, 0x7f, 0x4d, 0x9e, 0x3a, 0x82, 0x89, 0xbf, + 0xcf, 0xc4, 0xd6, 0xfd, 0xd1, 0x55, 0xfb, 0x7b, 0x47, 0x5c, 0xee, 0x75, + 0xba, 0x87, 0x8e, 0xe6, 0x77, 0xff, 0x7e, 0x93, 0x7c, 0xec, 0x27, 0x00, + 0xae, 0x75, 0xfc, 0x20, 0xf2, 0x4f, 0x07, 0x5f, 0xf9, 0x14, 0x81, 0x8d, + 0x42, 0x2c, 0xeb, 0xfb, 0x36, 0x02, 0x59, 0xa3, 0xaf, 0xb0, 0x39, 0x39, + 0xd7, 0xca, 0xff, 0x21, 0x58, 0x3a, 0xee, 0x41, 0xd5, 0x8a, 0xdb, 0x5a, + 0x4d, 0xb9, 0x52, 0x46, 0x80, 0xae, 0xef, 0x31, 0x32, 0xd2, 0xba, 0x58, + 0x27, 0x7e, 0x2e, 0xd8, 0x43, 0xb4, 0x57, 0x7e, 0x66, 0x30, 0x28, 0x75, + 0xe0, 0x7b, 0x47, 0x5f, 0xff, 0xff, 0xf6, 0xbe, 0x77, 0x27, 0x86, 0x77, + 0x96, 0xbe, 0x01, 0xbc, 0xe4, 0x7c, 0x99, 0x4d, 0xfe, 0x7c, 0xee, 0xd9, + 0xd5, 0x88, 0xec, 0x69, 0x37, 0x87, 0x2e, 0x07, 0xe7, 0x5d, 0xb6, 0xac, + 0x9d, 0x7b, 0xe4, 0x9a, 0x75, 0x41, 0xe9, 0xa8, 0x2e, 0xb1, 0xeb, 0xff, + 0xfb, 0x9f, 0x07, 0x36, 0x67, 0x25, 0xf2, 0x02, 0xf3, 0x68, 0xeb, 0xff, + 0xff, 0x87, 0x78, 0x50, 0x70, 0x3d, 0x49, 0xbe, 0x6b, 0x37, 0x97, 0x31, + 0x93, 0xab, 0x11, 0xac, 0x2c, 0x17, 0xde, 0x04, 0x4e, 0x75, 0xfe, 0x96, + 0x77, 0x17, 0x0d, 0x3a, 0x90, 0xf4, 0xfc, 0x45, 0x7f, 0xff, 0x6f, 0x2d, + 0x2f, 0x07, 0xe6, 0xd2, 0x76, 0x74, 0xce, 0x1d, 0x65, 0x73, 0xab, 0x0f, + 0xcd, 0xac, 0x17, 0xff, 0xfe, 0x67, 0xe0, 0xe3, 0x7a, 0x83, 0x80, 0xdf, + 0xdf, 0x1d, 0x9c, 0x50, 0xeb, 0xfc, 0xa0, 0x41, 0x1d, 0x18, 0x3a, 0xff, + 0x6f, 0x2d, 0x28, 0x08, 0xdc, 0xeb, 0xfc, 0xec, 0x82, 0x68, 0xf3, 0x9d, + 0x50, 0x98, 0x66, 0x38, 0xa1, 0x90, 0x9b, 0x5f, 0xfa, 0x34, 0x39, 0xb3, + 0xe4, 0x97, 0x23, 0xaf, 0xbf, 0xf2, 0x4e, 0x75, 0xfe, 0xf7, 0x50, 0x7f, + 0xfa, 0xb3, 0xaf, 0xf4, 0xf0, 0xb1, 0x8d, 0xff, 0x3a, 0xd1, 0x23, 0xe9, + 0x73, 0x5b, 0xff, 0x9f, 0x92, 0xf9, 0xe1, 0x89, 0x67, 0x8e, 0xa8, 0x57, + 0x4d, 0x8e, 0x89, 0x09, 0x4e, 0x46, 0x5b, 0xd3, 0xa7, 0x41, 0x18, 0x46, + 0x00, 0x9a, 0xff, 0xfb, 0x88, 0x05, 0x4c, 0x7c, 0xd0, 0x3f, 0x5e, 0x78, + 0xeb, 0x81, 0x23, 0xaf, 0xd1, 0xfe, 0xa7, 0xf1, 0xd7, 0x9f, 0xda, 0x3a, + 0xe0, 0x4e, 0x75, 0xe1, 0xf4, 0xd2, 0x36, 0x5c, 0x1b, 0xbf, 0x80, 0xdf, + 0x81, 0xdd, 0x93, 0xaa, 0x0f, 0x95, 0x0c, 0xef, 0xf7, 0x20, 0x31, 0xd8, + 0x91, 0xd7, 0xff, 0xd1, 0xef, 0x82, 0x0d, 0xaf, 0x99, 0xed, 0xbc, 0xf1, + 0xd4, 0x88, 0x89, 0x01, 0x8d, 0xff, 0xdd, 0x85, 0x3e, 0x78, 0x5f, 0xd1, + 0xe3, 0xaf, 0xf7, 0xcd, 0xe4, 0x9d, 0x02, 0xce, 0xaf, 0xcf, 0xec, 0x51, + 0x6f, 0xfe, 0xcd, 0x98, 0x1f, 0x9e, 0x51, 0x19, 0xd1, 0xd7, 0xfe, 0xe4, + 0xdf, 0x35, 0x09, 0x3b, 0xf8, 0xea, 0x84, 0x56, 0x04, 0x88, 0x09, 0x37, + 0x3f, 0xe7, 0x5f, 0xff, 0x7c, 0x18, 0xd4, 0x4e, 0x38, 0x1e, 0xa4, 0xc7, + 0x5f, 0xff, 0xfd, 0xae, 0x0c, 0x4d, 0xf3, 0xef, 0x92, 0x59, 0xbf, 0xb3, + 0x60, 0xe6, 0x8e, 0xae, 0x23, 0x1c, 0x54, 0x2b, 0xc8, 0xff, 0x04, 0x37, + 0x68, 0xeb, 0xa6, 0x91, 0xd5, 0x06, 0x87, 0x81, 0x57, 0xff, 0x0f, 0xb5, + 0xb1, 0x3d, 0x18, 0x33, 0x1d, 0x7e, 0xe2, 0x6a, 0x37, 0x3a, 0xb0, 0xfa, + 0xdd, 0x12, 0xff, 0x4e, 0xa8, 0x9a, 0x49, 0xed, 0x1d, 0x7e, 0x1f, 0x77, + 0x36, 0x8e, 0xbf, 0x4d, 0xa7, 0xe2, 0x87, 0x5e, 0x76, 0x79, 0x07, 0xa5, + 0x85, 0x35, 0x24, 0x6e, 0xa1, 0x07, 0x21, 0x17, 0x7f, 0xdd, 0x4e, 0x4d, + 0xd7, 0xce, 0x1d, 0x7f, 0xff, 0xff, 0x7f, 0xa1, 0xc7, 0xdf, 0xe0, 0x7a, + 0x0f, 0x83, 0x9b, 0xcb, 0x01, 0x38, 0xe3, 0xee, 0x75, 0x35, 0x18, 0xc8, + 0x71, 0x79, 0xdd, 0xa6, 0x8a, 0x62, 0xb0, 0xf2, 0x5a, 0x45, 0x7f, 0xec, + 0x1d, 0xe5, 0xaf, 0x47, 0x26, 0x3a, 0xf6, 0x27, 0xe7, 0x5b, 0x0e, 0xbd, + 0xb8, 0xe7, 0xe6, 0xab, 0x60, 0xdd, 0x22, 0x27, 0x9d, 0xa6, 0xff, 0x73, + 0xaf, 0xf1, 0x61, 0x98, 0xeb, 0xfd, 0xf3, 0x79, 0x0c, 0x66, 0x8e, 0xa4, + 0x3e, 0xa7, 0x36, 0xbf, 0xff, 0x7e, 0x9a, 0xf9, 0xd7, 0xd7, 0xa2, 0x6d, + 0x77, 0x0e, 0xbf, 0x93, 0xae, 0x93, 0xc1, 0xd7, 0xa5, 0x1b, 0x9d, 0x7f, + 0x96, 0x1e, 0xc4, 0xf8, 0xc9, 0xd5, 0x87, 0xf7, 0xb9, 0x5b, 0x8e, 0x5f, + 0xff, 0xe1, 0xc6, 0xfb, 0xd1, 0xed, 0x4c, 0x38, 0xcf, 0xc8, 0x56, 0x0e, + 0xbf, 0xf3, 0x61, 0x7d, 0xcd, 0x62, 0x09, 0xd5, 0x08, 0xa2, 0xeb, 0x3d, + 0xfb, 0x91, 0xb2, 0x38, 0x75, 0xfc, 0xe3, 0xf0, 0x30, 0x27, 0x56, 0x1f, + 0xb2, 0x11, 0x00, 0xa2, 0xa1, 0x95, 0xe1, 0x3a, 0xb4, 0x85, 0x83, 0x0c, + 0x05, 0x21, 0x52, 0xd8, 0xd2, 0x77, 0x8c, 0xb9, 0x12, 0x66, 0x8d, 0xa3, + 0x91, 0xa1, 0xae, 0x17, 0xfd, 0x84, 0x5f, 0xe4, 0x03, 0x0d, 0x3f, 0x46, + 0x8d, 0x7f, 0xdc, 0x76, 0x7e, 0x38, 0x5e, 0x73, 0xaf, 0xe7, 0x66, 0x61, + 0x40, 0x9d, 0x7f, 0xff, 0x83, 0x93, 0xb8, 0xfb, 0x50, 0xdf, 0x8b, 0x5a, + 0x0b, 0x4e, 0xbf, 0x83, 0xa7, 0x8d, 0xe4, 0x75, 0x42, 0x23, 0x9d, 0x86, + 0xff, 0xa2, 0x6e, 0xa4, 0x2d, 0xc2, 0x75, 0x28, 0x9a, 0x77, 0x0e, 0xc6, + 0x17, 0x60, 0x21, 0xbe, 0xc1, 0x51, 0x5c, 0xeb, 0xff, 0xff, 0xf7, 0x53, + 0xdd, 0xce, 0x46, 0xcf, 0x8b, 0x06, 0xd7, 0xcc, 0xde, 0x58, 0x01, 0xff, + 0x47, 0x5b, 0xc8, 0x8b, 0x1d, 0x12, 0x5f, 0xfa, 0x1b, 0xf0, 0x5f, 0x4b, + 0x81, 0x3a, 0xff, 0xfd, 0x99, 0xd4, 0x6f, 0x73, 0xe6, 0x81, 0xd8, 0x57, + 0x3a, 0xff, 0xfb, 0xdd, 0xcf, 0xfe, 0x2e, 0x33, 0xc1, 0xc1, 0x3a, 0xfe, + 0x70, 0xf3, 0x80, 0x9c, 0xeb, 0xf4, 0x60, 0xfb, 0x6c, 0xea, 0x69, 0xeb, + 0x2c, 0xba, 0xfb, 0xc9, 0xcc, 0x3a, 0xdb, 0xfc, 0x3c, 0x2c, 0x22, 0xb6, + 0xb1, 0x31, 0x27, 0x87, 0x45, 0x2d, 0x3d, 0x41, 0x3d, 0xf4, 0x6d, 0x57, + 0xff, 0xff, 0xe1, 0xcd, 0xe4, 0x9a, 0x1c, 0xd9, 0xdc, 0x9b, 0xb0, 0x33, + 0x7c, 0x76, 0xa6, 0xc3, 0xa9, 0x11, 0x7a, 0x03, 0x6b, 0xff, 0xc8, 0x1f, + 0x8b, 0x4f, 0x90, 0x17, 0x9b, 0x47, 0x5d, 0x29, 0x1d, 0x6e, 0x41, 0xf1, + 0xce, 0x9b, 0x7e, 0x94, 0x6f, 0x2d, 0x1d, 0x7f, 0xff, 0xff, 0xec, 0x15, + 0x3e, 0x27, 0x40, 0xc4, 0xc9, 0xe8, 0x58, 0xba, 0x9d, 0x46, 0x33, 0xbb, + 0xff, 0x01, 0x2a, 0xff, 0xff, 0xe6, 0xa3, 0x21, 0x07, 0x3e, 0x02, 0x27, + 0xd3, 0x7a, 0x0e, 0xee, 0xec, 0x9d, 0x70, 0x27, 0xdd, 0x34, 0x04, 0x28, + 0xd4, 0x27, 0xea, 0x17, 0x3a, 0x7b, 0x2a, 0xe5, 0xe1, 0x0a, 0x31, 0xb4, + 0x5f, 0xe7, 0x96, 0x2d, 0xc7, 0xf3, 0xaf, 0xb3, 0xb1, 0x31, 0xd7, 0x96, + 0xdf, 0x9d, 0x3d, 0x27, 0x31, 0xbf, 0xff, 0xfd, 0xc6, 0x8e, 0x6c, 0xf9, + 0xa4, 0xc1, 0xff, 0xe0, 0xe6, 0xc1, 0xcd, 0x6c, 0x3a, 0xff, 0x9b, 0x8e, + 0xbf, 0x9b, 0x70, 0xb3, 0xab, 0x11, 0x75, 0xc7, 0xeb, 0xff, 0xf2, 0x0f, + 0xbb, 0x9b, 0x5e, 0x9b, 0x15, 0xdc, 0x7f, 0x3a, 0xfd, 0x0c, 0xfc, 0xd4, + 0xc7, 0x5f, 0xf8, 0x67, 0x1c, 0xd9, 0xa0, 0x46, 0xe7, 0x5f, 0xf8, 0x3d, + 0x8d, 0xfe, 0x2a, 0xfd, 0x9f, 0xa1, 0xd5, 0x08, 0x8a, 0x9d, 0x02, 0x91, + 0x35, 0x4d, 0x11, 0x79, 0x68, 0x10, 0xb5, 0xbf, 0xf0, 0xc9, 0xbd, 0x4e, + 0x88, 0x27, 0x3a, 0xf7, 0xb1, 0x52, 0x75, 0x41, 0xee, 0xe1, 0xf5, 0xed, + 0xbc, 0xe9, 0xd7, 0x60, 0x4e, 0xa9, 0xd5, 0x9a, 0xca, 0x52, 0x1e, 0xa1, + 0x3f, 0xe2, 0x0d, 0x83, 0xd7, 0xe4, 0xf6, 0xb3, 0xf3, 0xaf, 0xdd, 0xcd, + 0x89, 0xb0, 0xeb, 0xc9, 0x9f, 0x9d, 0x7f, 0x06, 0x07, 0xaf, 0x23, 0xaf, + 0x40, 0x60, 0xeb, 0xf6, 0x7b, 0x4f, 0x37, 0xc3, 0xc5, 0x59, 0x5d, 0xfc, + 0xcf, 0xc5, 0x6d, 0x5a, 0xaa, 0x95, 0xb3, 0xaa, 0x48, 0x86, 0x44, 0x1b, + 0xff, 0xf7, 0x01, 0xce, 0x40, 0xe2, 0x89, 0xde, 0xe7, 0xd3, 0xaf, 0x80, + 0xfb, 0xf8, 0xea, 0x92, 0x7a, 0x21, 0x27, 0x50, 0xaa, 0x68, 0x73, 0x70, + 0x8b, 0xaa, 0xd4, 0x75, 0xfd, 0xa6, 0xb5, 0xc5, 0x43, 0xa9, 0x56, 0x36, + 0xfe, 0x0a, 0xbf, 0xc3, 0xf3, 0x66, 0xf2, 0xd4, 0xc7, 0x5d, 0x3e, 0xe7, + 0x5f, 0xba, 0xea, 0xf1, 0xf9, 0xd4, 0x13, 0xfb, 0x73, 0x9d, 0xa1, 0x8b, + 0xfd, 0xc9, 0x87, 0x3a, 0xfe, 0x3a, 0xa1, 0x30, 0x4c, 0x85, 0x0a, 0x18, + 0xdf, 0x93, 0x81, 0xc1, 0x3a, 0xfd, 0xfe, 0x7b, 0xec, 0xe7, 0x5f, 0xe6, + 0x7d, 0x9d, 0xf9, 0xbe, 0x8e, 0xa8, 0x3e, 0x27, 0x2b, 0xa9, 0x23, 0x6b, + 0xa6, 0x63, 0x08, 0x7b, 0xfe, 0xf7, 0x72, 0x4e, 0x39, 0xb9, 0xd7, 0xff, + 0xfc, 0x2f, 0xfe, 0xa7, 0xc4, 0x1f, 0x0e, 0x6c, 0xf9, 0xa6, 0x44, 0xea, + 0x14, 0x50, 0x78, 0xde, 0xff, 0xc9, 0x93, 0x7c, 0xd4, 0x75, 0xd5, 0xce, + 0xbf, 0xed, 0xf2, 0x37, 0x98, 0x61, 0x67, 0x5f, 0xdb, 0xeb, 0xb8, 0xfc, + 0x3a, 0xff, 0xff, 0xc8, 0xbe, 0x26, 0x6e, 0x20, 0xf4, 0x77, 0xe6, 0xc4, + 0xf4, 0xd0, 0x75, 0x3a, 0x27, 0x3c, 0x5b, 0x41, 0x4c, 0xe7, 0xa8, 0x5e, + 0x86, 0xad, 0xff, 0x67, 0x27, 0x84, 0xe6, 0x09, 0xd6, 0x59, 0xdf, 0x0d, + 0xb5, 0xe1, 0xc0, 0x9d, 0x50, 0x6f, 0x37, 0x22, 0xbf, 0xb7, 0xd6, 0x60, + 0xa8, 0x75, 0xf2, 0xfe, 0xc7, 0xe7, 0x5f, 0xfe, 0x9c, 0x3c, 0x76, 0x8e, + 0x6c, 0xe2, 0x68, 0xea, 0xc4, 0x4e, 0x21, 0x68, 0x09, 0x2f, 0xf3, 0xfb, + 0xaf, 0x37, 0xd5, 0x9d, 0x78, 0x1b, 0xfe, 0x75, 0x42, 0xb4, 0x1c, 0x8d, + 0x6d, 0x21, 0x51, 0xc8, 0x5e, 0xb9, 0x70, 0x9a, 0xdf, 0xde, 0x7e, 0xfc, + 0x0c, 0x1d, 0x7f, 0xfb, 0xda, 0xfb, 0xaf, 0x9e, 0x18, 0x96, 0x78, 0xeb, + 0xfd, 0xe4, 0x9f, 0x3a, 0x0f, 0x1d, 0x69, 0x8e, 0xbf, 0xb0, 0x19, 0xd6, + 0xce, 0x75, 0xd9, 0xbc, 0x1b, 0xed, 0x08, 0xdf, 0xdd, 0x79, 0x2f, 0x88, + 0x75, 0xff, 0xca, 0x28, 0xfe, 0xd7, 0x86, 0x37, 0x91, 0xd7, 0xf7, 0x86, + 0x25, 0x9e, 0x3a, 0xa0, 0xfc, 0x64, 0x8d, 0x72, 0x68, 0xeb, 0xdc, 0xcd, + 0xce, 0xa0, 0x9b, 0x1f, 0xc5, 0x6f, 0xff, 0x3a, 0x9e, 0x52, 0x06, 0x59, + 0xd4, 0x59, 0xd7, 0xe4, 0xd6, 0xa1, 0x67, 0x52, 0x22, 0x44, 0x48, 0xb6, + 0x24, 0xd4, 0x2a, 0xc8, 0xc2, 0xe5, 0x13, 0x51, 0xc7, 0xf2, 0xc1, 0x84, + 0xe8, 0x21, 0xc7, 0x7e, 0x0a, 0x0b, 0x84, 0xeb, 0xff, 0xf4, 0xbb, 0x93, + 0x76, 0x05, 0x41, 0xcf, 0x74, 0x07, 0x52, 0x1f, 0xd7, 0x09, 0x6f, 0xff, + 0xf2, 0x66, 0xf2, 0xd7, 0xbb, 0x0b, 0x84, 0x0f, 0xc8, 0x56, 0x0e, 0xbf, + 0xce, 0x3f, 0x1b, 0xaf, 0xc2, 0x75, 0xff, 0x81, 0xaf, 0x8b, 0xfb, 0xd7, + 0xec, 0x1d, 0x7e, 0xcf, 0x03, 0x37, 0x3a, 0xf2, 0x99, 0xb9, 0xd7, 0x44, + 0xdf, 0x0f, 0x13, 0xc4, 0xf4, 0x28, 0xb6, 0x04, 0x21, 0xaf, 0xff, 0xff, + 0xc0, 0x1f, 0x8c, 0xbe, 0xf2, 0xe3, 0xff, 0xf3, 0x40, 0x8d, 0xfb, 0x88, + 0x38, 0xa1, 0xd7, 0xff, 0xe0, 0x73, 0x99, 0xed, 0x75, 0x33, 0xe7, 0x7f, + 0x83, 0xab, 0x11, 0xc1, 0xd8, 0x44, 0xdf, 0xb0, 0x5b, 0xf5, 0x67, 0x5f, + 0xfd, 0xdc, 0x81, 0x98, 0x73, 0xda, 0x73, 0xad, 0x2f, 0x1f, 0x4e, 0xd1, + 0x45, 0xff, 0xf8, 0x38, 0xbf, 0x9b, 0x5e, 0x8d, 0x4d, 0x27, 0xe4, 0xe7, + 0x5f, 0xff, 0xde, 0x49, 0xf0, 0x3f, 0x16, 0xf2, 0xe2, 0x4e, 0xeb, 0x3a, + 0xff, 0x4e, 0xeb, 0x18, 0xe4, 0xc7, 0x5f, 0xf6, 0xf8, 0xa7, 0xeb, 0xcf, + 0x9c, 0xc4, 0x48, 0x22, 0xed, 0xff, 0x60, 0xcf, 0xf3, 0xf7, 0x79, 0x8e, + 0xbf, 0xee, 0x4f, 0x13, 0xce, 0x0e, 0x4e, 0x75, 0xff, 0xbe, 0x4d, 0xd0, + 0x28, 0x98, 0x2a, 0x1d, 0x7f, 0x87, 0xe6, 0x81, 0xb6, 0x0e, 0x1d, 0x58, + 0x7f, 0x40, 0x42, 0xa8, 0x46, 0xc6, 0xa1, 0x6f, 0x7f, 0xfa, 0x7f, 0x9a, + 0xe8, 0x3e, 0x7b, 0x5a, 0x8e, 0x1d, 0x7f, 0xfd, 0xd8, 0x9f, 0xe0, 0xe6, + 0xc7, 0xef, 0x63, 0x73, 0xaf, 0xff, 0xfb, 0x7d, 0x26, 0x33, 0xf3, 0xb9, + 0xed, 0x64, 0xff, 0x31, 0x02, 0x75, 0x05, 0x17, 0xd8, 0xa7, 0x7f, 0x4f, + 0xe9, 0x86, 0x16, 0x75, 0xff, 0xfd, 0x93, 0xe2, 0x04, 0x41, 0xdf, 0x90, + 0x17, 0x9b, 0x47, 0x56, 0x27, 0x74, 0x91, 0x87, 0x39, 0x16, 0x8b, 0xaa, + 0x75, 0xf8, 0x80, 0xb3, 0x29, 0x0e, 0xb6, 0xc6, 0x0f, 0xbc, 0x24, 0x10, + 0xaf, 0x90, 0xec, 0x5a, 0xa6, 0xa3, 0x13, 0xf4, 0x7c, 0x37, 0xfb, 0xc3, + 0x9e, 0xee, 0x4e, 0x75, 0xff, 0x9f, 0x9d, 0xcf, 0x40, 0xa7, 0xe7, 0x5f, + 0xff, 0x0e, 0x4f, 0xf3, 0xf0, 0x7b, 0x31, 0x7f, 0xb2, 0x75, 0xf4, 0xbc, + 0x93, 0x9d, 0x7f, 0xd8, 0xce, 0xf2, 0xd7, 0xcf, 0x21, 0xd7, 0xfe, 0x94, + 0x67, 0xfd, 0xcc, 0x16, 0x9d, 0x7f, 0xfb, 0xa8, 0x21, 0xf9, 0xf5, 0xa3, + 0x9d, 0xc3, 0xab, 0x11, 0x0f, 0x31, 0xe5, 0xff, 0x75, 0x17, 0x18, 0x3e, + 0xd1, 0xd7, 0xff, 0xf8, 0x1e, 0xe0, 0x26, 0xf9, 0xe9, 0xba, 0x0f, 0xfc, + 0x99, 0xb4, 0x75, 0xf4, 0x36, 0x17, 0xf1, 0x18, 0x6d, 0x23, 0x13, 0x6a, + 0x85, 0x56, 0x2d, 0x32, 0xe1, 0xe3, 0xaa, 0x09, 0x16, 0xd4, 0x70, 0xd7, + 0xff, 0xf7, 0x31, 0xd7, 0xf1, 0x47, 0xdf, 0xb9, 0xde, 0xc7, 0x8e, 0xbf, + 0xd0, 0xbc, 0xce, 0x4d, 0x23, 0xaf, 0x93, 0xc9, 0x07, 0x5f, 0xff, 0xfe, + 0x14, 0x53, 0xaf, 0x37, 0xc1, 0x06, 0xd7, 0xcc, 0xde, 0x58, 0x01, 0xff, + 0x47, 0x5f, 0xba, 0x90, 0x33, 0x9d, 0x77, 0xa1, 0x68, 0xa6, 0xd9, 0x08, + 0x0a, 0x92, 0x3e, 0x92, 0x18, 0xb5, 0x0c, 0xd1, 0xac, 0x9f, 0xa9, 0x49, + 0x6c, 0x5c, 0x5f, 0xea, 0xeb, 0xc6, 0x59, 0x7e, 0x81, 0xf2, 0x6c, 0x3a, + 0xfb, 0xda, 0x7f, 0xce, 0xbf, 0xfb, 0xa9, 0xf1, 0x38, 0x09, 0xdf, 0x8d, + 0x3a, 0xf9, 0x3a, 0xf3, 0x9d, 0x7d, 0xb2, 0x3d, 0x07, 0x5f, 0xb5, 0x9e, + 0x4d, 0x1d, 0x7e, 0x02, 0xa4, 0x5f, 0xc7, 0x5f, 0xdd, 0x79, 0xfe, 0x4b, + 0xc7, 0x5f, 0x9f, 0x83, 0xba, 0x1d, 0x50, 0x88, 0x04, 0x2a, 0xf1, 0x85, + 0x05, 0x3a, 0x6c, 0x27, 0x50, 0x89, 0xa8, 0xc8, 0x43, 0x31, 0x17, 0xa1, + 0x4d, 0x7f, 0xbb, 0x08, 0x2f, 0xc5, 0x0e, 0xbf, 0xa1, 0x05, 0xf8, 0xa1, + 0xd7, 0xfb, 0xf7, 0xff, 0x9c, 0x4e, 0x7c, 0x3d, 0xce, 0x98, 0xdb, 0xf3, + 0xaf, 0xe8, 0xe4, 0xf1, 0xc9, 0xce, 0xbc, 0x07, 0xd1, 0xd5, 0x23, 0xc9, + 0xfa, 0x5d, 0x7f, 0xff, 0x27, 0x3e, 0x62, 0x60, 0xa9, 0xd4, 0xc5, 0xe3, + 0x4e, 0xbf, 0xff, 0xe4, 0x9f, 0x90, 0xbd, 0x02, 0x3e, 0x47, 0x20, 0x3d, + 0x85, 0x9d, 0x58, 0x8c, 0x0e, 0x2c, 0xdf, 0xbf, 0xd2, 0x6e, 0xc9, 0xd7, + 0xfe, 0xe6, 0x6f, 0xdd, 0xe1, 0x73, 0xc1, 0xd7, 0xff, 0xff, 0xb9, 0xc4, + 0x9f, 0xe7, 0x73, 0xc3, 0x13, 0x77, 0x27, 0x8d, 0xfc, 0x06, 0x9d, 0x7f, + 0xff, 0xf4, 0x29, 0xd8, 0xf8, 0x38, 0x05, 0x3e, 0x6f, 0x2d, 0x20, 0xfd, + 0x89, 0xce, 0xbf, 0x6f, 0xa4, 0xc1, 0x3a, 0xb1, 0x13, 0xe0, 0x79, 0xa4, + 0x4c, 0xf7, 0xb1, 0x8d, 0xdf, 0xfd, 0x2d, 0x22, 0x9d, 0x84, 0x9e, 0x14, + 0x3a, 0xff, 0x84, 0x13, 0x0e, 0x75, 0xfc, 0x75, 0xfe, 0xec, 0x32, 0x1e, + 0xba, 0xce, 0xbf, 0xe5, 0xe6, 0xbe, 0x4c, 0x30, 0xb3, 0xa8, 0x27, 0xda, + 0xb3, 0x3b, 0xff, 0xfe, 0x7e, 0x77, 0x3c, 0x98, 0x33, 0xea, 0x30, 0x43, + 0xd8, 0x3a, 0xfb, 0xdf, 0x27, 0xe1, 0xd5, 0xba, 0x21, 0xdd, 0x8a, 0xff, + 0xff, 0xdb, 0xe4, 0xe0, 0xda, 0xf9, 0xbc, 0xbd, 0x0c, 0xfc, 0xce, 0x7f, + 0xfc, 0x1d, 0x7f, 0xf9, 0x97, 0x19, 0xd6, 0x04, 0x0a, 0x0a, 0x1d, 0x7f, + 0x4d, 0xbc, 0x81, 0x1e, 0x3a, 0xff, 0xba, 0xeb, 0x1c, 0xeb, 0xf8, 0xeb, + 0xec, 0xe7, 0xec, 0x9d, 0x50, 0x88, 0x8d, 0x17, 0xf8, 0xda, 0xfe, 0xcf, + 0x73, 0x99, 0x23, 0xaf, 0xe1, 0xce, 0x8e, 0x34, 0xeb, 0xe1, 0xcd, 0x7c, + 0x98, 0xf5, 0xbc, 0x59, 0x7f, 0xd8, 0xbe, 0xc2, 0x70, 0x0a, 0xe7, 0x50, + 0x57, 0x7a, 0xb0, 0x89, 0x42, 0xa6, 0xc6, 0xfb, 0xb9, 0x4a, 0x22, 0xf2, + 0x14, 0x9d, 0x85, 0x4b, 0x91, 0xe9, 0xe7, 0xd0, 0xd0, 0xd9, 0x08, 0x5f, + 0xa7, 0x77, 0xfe, 0xc6, 0x47, 0x01, 0x8a, 0x4b, 0xf3, 0xaf, 0xfc, 0x39, + 0xf3, 0x99, 0xd1, 0xc9, 0x8e, 0xbf, 0xff, 0xdd, 0x7f, 0xf5, 0xf0, 0x73, + 0x60, 0xe6, 0xb1, 0x70, 0xd3, 0xa8, 0x51, 0x41, 0xa3, 0xea, 0x55, 0x99, + 0x1f, 0x70, 0xb5, 0x93, 0xd9, 0xdb, 0xc3, 0x49, 0xe1, 0xbf, 0x7f, 0x67, + 0x7e, 0x8e, 0xff, 0x9d, 0x7f, 0x77, 0x07, 0xdf, 0x80, 0xeb, 0xf0, 0xc2, + 0xdc, 0x27, 0x5f, 0xec, 0x9b, 0xb9, 0xe8, 0x09, 0xd7, 0xf0, 0xf9, 0xd6, + 0x9e, 0x3a, 0xd2, 0x3a, 0xa0, 0xdd, 0xf8, 0xae, 0xf0, 0xb6, 0x0e, 0xbf, + 0xff, 0xfe, 0xee, 0x7b, 0x4f, 0x37, 0xc1, 0xcd, 0xe5, 0x80, 0x9c, 0x70, + 0x3d, 0x49, 0x8e, 0xb8, 0x0a, 0x1d, 0x48, 0x8b, 0x1e, 0x0d, 0x7a, 0x10, + 0x17, 0xf6, 0x4e, 0x39, 0xbe, 0x8e, 0xbf, 0xf8, 0x7f, 0xdb, 0xce, 0xa4, + 0x2d, 0xc2, 0x75, 0xff, 0xff, 0xfa, 0x5a, 0xd0, 0x23, 0xc8, 0x1c, 0x19, + 0xbe, 0x0e, 0x72, 0x07, 0xdd, 0xcd, 0xa3, 0xaf, 0xfe, 0xde, 0x5a, 0xc5, + 0xef, 0x1d, 0xec, 0x1d, 0x5b, 0xa3, 0x2b, 0x90, 0x85, 0xb6, 0x8e, 0xac, + 0x4d, 0x20, 0x11, 0x87, 0xfd, 0x29, 0xbf, 0xb3, 0x79, 0x47, 0xf0, 0x75, + 0xf8, 0x73, 0xaf, 0xe3, 0xad, 0x1b, 0x9e, 0x92, 0xcb, 0x6f, 0xbe, 0x36, + 0x76, 0x4e, 0xbf, 0x4f, 0xf0, 0x11, 0x31, 0xd7, 0xff, 0xfc, 0x31, 0xfe, + 0xf2, 0xd0, 0x23, 0xc3, 0x81, 0x4c, 0xe4, 0xc7, 0x53, 0xa2, 0x47, 0xc5, + 0x75, 0x0b, 0x9e, 0x81, 0x30, 0x42, 0xd9, 0x89, 0x7a, 0xda, 0xf0, 0xd1, + 0x13, 0x4d, 0x46, 0xea, 0x08, 0x45, 0x6c, 0x28, 0xfb, 0x0b, 0x7b, 0xf4, + 0x93, 0x99, 0xb9, 0xd7, 0xb5, 0xdc, 0x3a, 0xfd, 0x9a, 0x9f, 0x19, 0x3a, + 0xb7, 0x3e, 0xa9, 0x89, 0xfa, 0x37, 0x7f, 0xfd, 0x3e, 0x34, 0x3d, 0x4c, + 0x53, 0xe2, 0x80, 0x83, 0xaf, 0xfb, 0xe7, 0xdf, 0x26, 0xc8, 0x16, 0x9d, + 0x48, 0x89, 0x0e, 0xa9, 0xdf, 0xfe, 0x8d, 0xe5, 0xaf, 0x3c, 0xfb, 0x43, + 0x9b, 0x9d, 0x7f, 0xdd, 0x9d, 0x30, 0x77, 0x96, 0x8e, 0xbf, 0xed, 0xfb, + 0x8d, 0x1c, 0x02, 0xb9, 0xd6, 0x94, 0x1f, 0xa6, 0x1c, 0xdf, 0xc9, 0xbf, + 0xfc, 0x70, 0x9d, 0x7e, 0xc4, 0xce, 0x7e, 0x75, 0x74, 0xf5, 0x04, 0xba, + 0xfb, 0x6b, 0xd9, 0xd3, 0xae, 0x45, 0x9d, 0x7f, 0xff, 0xed, 0xe4, 0xfb, + 0xfc, 0x10, 0x6d, 0x7c, 0xcd, 0xe5, 0x80, 0x1f, 0xf4, 0x75, 0x2d, 0x11, + 0x7b, 0x42, 0xb7, 0xb6, 0xd1, 0x52, 0x75, 0x7c, 0x4c, 0x62, 0x72, 0x1c, + 0x85, 0x7e, 0xd9, 0x35, 0xff, 0xff, 0xfa, 0x37, 0xd0, 0x23, 0x7f, 0x9d, + 0xc0, 0xfc, 0x1c, 0x02, 0x9f, 0x35, 0xff, 0xe9, 0xe3, 0xaf, 0xd0, 0x3b, + 0xbc, 0xe7, 0x5f, 0xff, 0xff, 0xfb, 0x1b, 0x1d, 0x85, 0xfb, 0x35, 0xa8, + 0xe7, 0x20, 0x72, 0x7c, 0x06, 0x81, 0x30, 0xc2, 0xce, 0xbc, 0x0e, 0x28, + 0x75, 0x2d, 0x16, 0x9b, 0x70, 0x97, 0xbf, 0x3f, 0xff, 0x5e, 0x73, 0xab, + 0x0f, 0x55, 0x0a, 0xef, 0x27, 0xf0, 0x75, 0xfc, 0x11, 0xce, 0xbf, 0x8e, + 0xbf, 0x7b, 0x79, 0x27, 0x0e, 0xac, 0x3d, 0x3d, 0x15, 0xd4, 0xe8, 0x8f, + 0xfd, 0xba, 0xff, 0x4e, 0x08, 0xf2, 0xd3, 0xc7, 0x5f, 0xfa, 0x14, 0xda, + 0x06, 0x0c, 0xdf, 0x56, 0x75, 0x61, 0xfb, 0xee, 0x67, 0x7f, 0xec, 0xcf, + 0xf5, 0xf3, 0x9a, 0x0e, 0x8e, 0xbf, 0xdc, 0xc6, 0xf5, 0x39, 0x31, 0xd7, + 0x67, 0x82, 0x7e, 0x98, 0x83, 0x7d, 0x3a, 0x0f, 0x8e, 0xbf, 0x67, 0x7a, + 0xf2, 0x3a, 0xfe, 0xf2, 0x72, 0x7c, 0x69, 0xd5, 0x0b, 0xf7, 0xb9, 0x0c, + 0x15, 0x08, 0xb7, 0x86, 0x12, 0x47, 0x25, 0xc4, 0x85, 0xc2, 0x37, 0xb1, + 0x98, 0x3c, 0x2b, 0xc6, 0x13, 0x9a, 0x84, 0xb0, 0x0b, 0x36, 0xc8, 0x76, + 0x89, 0xaf, 0x3b, 0x70, 0xeb, 0xff, 0x4d, 0xf3, 0xc3, 0x8c, 0xe2, 0x68, + 0xea, 0x55, 0x1e, 0xd4, 0x0d, 0x51, 0xd7, 0xf6, 0x2e, 0x3a, 0xfd, 0x3a, + 0xef, 0x93, 0x1d, 0x5f, 0x0f, 0x10, 0x25, 0x77, 0xff, 0xdb, 0xc8, 0x63, + 0xe2, 0xc6, 0x14, 0xf2, 0x4e, 0x75, 0x42, 0x31, 0x31, 0x39, 0x09, 0x2f, + 0xdc, 0xf8, 0x3b, 0x19, 0x3a, 0xfb, 0xaf, 0xfc, 0x1d, 0x7b, 0xb9, 0xc3, + 0xaa, 0x0f, 0xa1, 0xcb, 0x36, 0x88, 0x6f, 0xe9, 0xe6, 0x92, 0xab, 0x93, + 0x9d, 0x7e, 0x5a, 0x07, 0x02, 0x75, 0xa6, 0x3a, 0xe8, 0x59, 0xd6, 0xf1, + 0xd5, 0xc3, 0x4a, 0xe2, 0xb4, 0x13, 0xd6, 0xe9, 0xb5, 0xee, 0x44, 0xc7, + 0x5e, 0xd3, 0xee, 0x75, 0x39, 0xb8, 0xf0, 0xe5, 0xd3, 0x39, 0xd7, 0xf3, + 0xb3, 0x1e, 0xc9, 0xce, 0xbf, 0x93, 0x9b, 0xc8, 0x60, 0xeb, 0xfc, 0x1e, + 0xc6, 0xf2, 0xcf, 0x1d, 0x5d, 0x3d, 0xff, 0x16, 0x52, 0xb2, 0x9f, 0x7c, + 0x1a, 0xe3, 0xe2, 0x2d, 0x2c, 0x80, 0x45, 0x81, 0x08, 0xcb, 0xfc, 0xce, + 0x48, 0x40, 0xfa, 0x3a, 0xfd, 0xbb, 0x2e, 0x3f, 0x9d, 0x70, 0xa8, 0x75, + 0xb4, 0x86, 0xfc, 0x05, 0x37, 0xff, 0xf4, 0x2c, 0x71, 0xbb, 0xf8, 0x5f, + 0xab, 0x8c, 0xf1, 0xd7, 0xff, 0xe8, 0xe4, 0x37, 0x17, 0x0d, 0x92, 0x68, + 0x0b, 0x3a, 0xa1, 0x34, 0x29, 0x9c, 0x7a, 0x4d, 0xb6, 0xb1, 0x7f, 0x73, + 0x21, 0x48, 0x13, 0xaf, 0x0b, 0xac, 0xeb, 0xbf, 0x83, 0xaa, 0x47, 0xb6, + 0x85, 0x62, 0x35, 0x4a, 0xcb, 0xf0, 0x0c, 0x2b, 0x6e, 0xca, 0xa8, 0xfb, + 0x95, 0xa2, 0xcc, 0x4b, 0x87, 0x9e, 0x3a, 0x09, 0x42, 0x08, 0x33, 0x95, + 0x79, 0x4b, 0x6e, 0x52, 0x52, 0xbb, 0x67, 0x77, 0x77, 0x97, 0xac, 0x92, + 0x8b, 0x26, 0x94, 0xe9, 0xc9, 0xc1, 0x55, 0xcb, 0x2c, 0xed, 0x38, 0x09, + 0xe5, 0x09, 0x7f, 0x0c, 0x61, 0xa4, 0xa4, 0xea, 0x75, 0x5f, 0xd4, 0x8d, + 0x80, 0x46, 0x93, 0xb2, 0x1d, 0x2c, 0xc2, 0x57, 0x6e, 0x50, 0xff, 0xd8, + 0xeb, 0x76, 0xa1, 0x39, 0x7f, 0xff, 0x01, 0xac, 0x6f, 0xee, 0x46, 0x6e, + 0xaa, 0x0b, 0xba, 0x87, 0x53, 0x0a, 0xaa, 0x92, 0x52, 0x45, 0xfe, 0x57, + 0x74, 0xf6, 0x90, 0x4e, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x53, 0xb7, 0x66, + 0xe7, 0x5f, 0xfe, 0x00, 0x05, 0x06, 0x3a, 0x8b, 0xcd, 0x1d, 0x66, 0x21, + 0x18, 0x58, 0x67, 0xb9, 0x9a, 0xc5, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x15, + 0x1d, 0xff, 0x9e, 0x4c, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0xd1, 0x7c, 0x31, + 0x9b, 0x9d, 0x58, 0x89, 0xd5, 0x99, 0xf9, 0x2a, 0xff, 0x7d, 0x7d, 0x8c, + 0x79, 0x27, 0x3a, 0x98, 0x3e, 0x78, 0x2f, 0xbf, 0x71, 0xae, 0xed, 0x34, + 0x55, 0xf7, 0xf6, 0x6c, 0x81, 0xe8, 0x0e, 0xb3, 0x18, 0x7c, 0x1c, 0x33, + 0xbf, 0x71, 0xae, 0xed, 0x34, 0x56, 0xd7, 0xfd, 0x26, 0x33, 0x8d, 0x77, + 0x69, 0xa2, 0x41, 0xb3, 0x18, 0x7f, 0x0e, 0x67, 0x7f, 0xf3, 0x0f, 0x26, + 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x43, 0xbf, 0xf6, 0x98, 0xcf, 0x20, 0x70, + 0x66, 0x3a, 0xf3, 0xbb, 0x4f, 0x18, 0x1d, 0x41, 0xf2, 0xb4, 0xfa, 0xee, + 0xab, 0x9d, 0x7f, 0xe9, 0x76, 0x3d, 0xa5, 0x63, 0x4a, 0xd8, 0x9d, 0x7f, + 0xf9, 0x57, 0x2a, 0xe5, 0x63, 0xb0, 0xb1, 0x7e, 0xa7, 0x0e, 0xb6, 0xe7, + 0x5c, 0x82, 0x75, 0xfd, 0x01, 0x8f, 0x38, 0x4e, 0xa0, 0x9e, 0x84, 0xc2, + 0x3e, 0x14, 0xbf, 0xf9, 0x06, 0x78, 0x53, 0xef, 0xff, 0xc6, 0xe7, 0x5f, + 0xb3, 0x07, 0xfd, 0x1d, 0x7e, 0x70, 0xfd, 0x81, 0x3a, 0xff, 0xdc, 0xf7, + 0xd1, 0x76, 0xe0, 0xb4, 0xeb, 0xe6, 0xbb, 0xb4, 0xd1, 0x62, 0x5e, 0x00, + 0xc8, 0xeb, 0xfc, 0xd8, 0xce, 0x7f, 0xff, 0x8e, 0xa9, 0xd1, 0xc3, 0x84, + 0xfc, 0x3e, 0xf1, 0x68, 0x06, 0xef, 0xd9, 0xc8, 0x15, 0x0e, 0xbf, 0x7d, + 0xdb, 0xce, 0x41, 0xd7, 0xb5, 0x02, 0x75, 0xbb, 0x07, 0x8a, 0x85, 0x77, + 0xff, 0x46, 0x6b, 0x04, 0x29, 0xfc, 0x09, 0xd7, 0x86, 0x27, 0x3a, 0x84, + 0xf6, 0xc0, 0x81, 0x7d, 0x1c, 0x85, 0x9d, 0x52, 0x3c, 0x1d, 0x10, 0xde, + 0x5b, 0xf8, 0xeb, 0x93, 0xf3, 0xab, 0x86, 0xc7, 0x6c, 0x6e, 0xfc, 0x9b, + 0x00, 0xfa, 0x3a, 0xff, 0x83, 0xdc, 0x5e, 0x3f, 0x27, 0x3a, 0xfd, 0xef, + 0x3c, 0xb4, 0x75, 0xff, 0x81, 0x9b, 0x87, 0x67, 0x71, 0xe6, 0x3a, 0xb7, + 0x3e, 0x8d, 0x84, 0xf6, 0x91, 0xd7, 0xd9, 0x8c, 0xe8, 0xea, 0x83, 0x63, + 0xe1, 0x0b, 0x80, 0x27, 0x54, 0x26, 0x57, 0x90, 0xa0, 0xe2, 0xb6, 0x88, + 0x2f, 0xfa, 0x35, 0xf7, 0x39, 0x99, 0x31, 0xd7, 0xf7, 0x25, 0xfe, 0x64, + 0xc7, 0x5f, 0x3c, 0x26, 0xd9, 0xd5, 0x87, 0xa1, 0xc2, 0xeb, 0xe9, 0x7d, + 0xec, 0x1d, 0x7b, 0x91, 0x23, 0xa9, 0xcd, 0xf6, 0xc2, 0x3b, 0xfa, 0x17, + 0x89, 0xc9, 0x8e, 0xbe, 0xfb, 0x1b, 0x5a, 0x3a, 0xfd, 0x81, 0xec, 0x74, + 0xeb, 0xee, 0x23, 0x2a, 0xe7, 0x50, 0x9e, 0x5e, 0x89, 0xa8, 0x28, 0x92, + 0xd3, 0x8d, 0x42, 0x6c, 0x48, 0xbf, 0xd2, 0x27, 0x85, 0xf5, 0xfc, 0x82, + 0xeb, 0x8e, 0x9d, 0x7f, 0xfa, 0x17, 0x12, 0x08, 0xc7, 0x5f, 0x38, 0x75, + 0x1d, 0x52, 0x3d, 0x0d, 0xb4, 0x6b, 0xde, 0xcf, 0xce, 0xbf, 0x96, 0x9a, + 0xd2, 0x04, 0xeb, 0xcf, 0xc5, 0x0e, 0xa0, 0x1e, 0x43, 0x25, 0x97, 0xf9, + 0xa3, 0x9b, 0x07, 0x34, 0x75, 0xff, 0x6f, 0x27, 0xc1, 0xcf, 0x68, 0xeb, + 0xff, 0x66, 0xf2, 0xec, 0x69, 0x4e, 0xc1, 0xd5, 0x24, 0xf3, 0xb7, 0x7a, + 0x98, 0x97, 0x8c, 0x9d, 0x23, 0x13, 0x2d, 0xa3, 0x7b, 0x6d, 0x9d, 0x74, + 0xb4, 0x75, 0x9e, 0x46, 0xa7, 0x71, 0x3b, 0xef, 0x20, 0xb2, 0x55, 0x80, + 0x75, 0xa3, 0x0d, 0x8f, 0x48, 0x6f, 0xf9, 0xc7, 0xda, 0xdf, 0x4e, 0xae, + 0x75, 0x3a, 0x2e, 0x3f, 0x58, 0x01, 0x2d, 0xfd, 0xd4, 0xd7, 0x39, 0x87, + 0x5f, 0xfa, 0x19, 0xfb, 0x3e, 0xb1, 0x70, 0xae, 0x75, 0xce, 0xc9, 0xd6, + 0xc6, 0xa2, 0x1b, 0xc5, 0x9b, 0x11, 0x2f, 0xfe, 0xeb, 0xa7, 0xa5, 0x8a, + 0x0e, 0x7e, 0x75, 0xf8, 0x66, 0x8e, 0xc1, 0xd7, 0xec, 0xee, 0xee, 0xae, + 0x75, 0xf7, 0xfa, 0x81, 0x3a, 0xff, 0x73, 0xae, 0x9a, 0x4d, 0x87, 0x54, + 0x1e, 0xa6, 0x10, 0xd2, 0x26, 0x0e, 0xe8, 0x62, 0x4d, 0xa7, 0xeb, 0xf9, + 0x98, 0xe7, 0x1e, 0x63, 0xaf, 0xf8, 0x30, 0xdf, 0xbf, 0xff, 0x1b, 0x9d, + 0x7f, 0xcf, 0xcc, 0x5a, 0x6d, 0xc2, 0xce, 0xa6, 0x9f, 0xb0, 0x0f, 0x6f, + 0xbd, 0x1b, 0xc8, 0xeb, 0xf9, 0x3f, 0xdb, 0x14, 0xfc, 0xea, 0x9c, 0xf4, + 0xb8, 0x45, 0x50, 0x99, 0xde, 0x42, 0x91, 0xdd, 0x2f, 0xed, 0x9c, 0x78, + 0x4d, 0xb3, 0xad, 0x87, 0x52, 0xcd, 0xf8, 0x98, 0x5f, 0xfb, 0xb8, 0x10, + 0xa6, 0xf9, 0xbf, 0x8e, 0xbf, 0xbe, 0x07, 0xeb, 0xf3, 0x87, 0x54, 0xe7, + 0xe0, 0x13, 0xfb, 0xe7, 0x84, 0xdb, 0x3a, 0xff, 0xa1, 0x03, 0xe1, 0x7d, + 0xf4, 0x75, 0x41, 0xfe, 0x04, 0x8c, 0x48, 0xa9, 0x58, 0x6c, 0x19, 0x15, + 0xb1, 0x95, 0x6a, 0x91, 0x10, 0xa9, 0x91, 0x80, 0x52, 0x72, 0x30, 0x75, + 0x12, 0x9a, 0xd7, 0xbc, 0x30, 0x91, 0x4e, 0x62, 0x4e, 0x46, 0xa6, 0xb4, + 0x1e, 0xc7, 0xd6, 0xf2, 0x83, 0xbf, 0x8d, 0x28, 0x61, 0x6d, 0xa8, 0xcf, + 0xbd, 0x1b, 0xb0, 0x1c, 0xbe, 0xc6, 0x19, 0x7f, 0xf7, 0x52, 0x3d, 0xd7, + 0x53, 0x07, 0xf3, 0xaf, 0xec, 0xf4, 0x22, 0xf4, 0x75, 0xfe, 0x0c, 0x4b, + 0x39, 0x9a, 0x3a, 0xf6, 0xbe, 0xe8, 0xeb, 0xff, 0xec, 0xde, 0x5e, 0x04, + 0xec, 0x75, 0xd6, 0x9a, 0x3a, 0xff, 0x80, 0xf8, 0x14, 0xdc, 0x5c, 0xeb, + 0xde, 0x18, 0x3a, 0xee, 0xb1, 0x89, 0xaf, 0xcc, 0x86, 0xb2, 0xb7, 0x31, + 0x11, 0xed, 0x29, 0x7d, 0x36, 0xa6, 0x15, 0xa7, 0x44, 0xad, 0xcb, 0xfb, + 0x38, 0xd7, 0x76, 0x9a, 0x2c, 0xdb, 0xff, 0x47, 0x3f, 0xf6, 0xbb, 0x88, + 0x13, 0xaf, 0x90, 0x5e, 0x73, 0xab, 0xa7, 0xbd, 0xa3, 0xeb, 0xe6, 0x3b, + 0x1d, 0x3a, 0x98, 0x3c, 0x4d, 0xa2, 0x2a, 0x61, 0x30, 0x07, 0x86, 0xd5, + 0xfe, 0x5b, 0x10, 0x8b, 0xfb, 0xc3, 0xae, 0xc0, 0x9d, 0x7f, 0xe7, 0x93, + 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x40, 0x5f, 0xe4, 0x5c, 0x2b, 0xf7, 0x27, + 0x3a, 0xcc, 0x62, 0x25, 0x16, 0x2b, 0xd4, 0xab, 0xf9, 0xfd, 0xa9, 0x27, + 0xe7, 0x5f, 0xd2, 0x63, 0x26, 0x89, 0x1d, 0x4c, 0x1e, 0xdc, 0x16, 0xdc, + 0x0e, 0x9d, 0x7f, 0x6a, 0x16, 0x31, 0x31, 0xd6, 0xe9, 0xd7, 0xbe, 0x8c, + 0xc7, 0x5d, 0x9e, 0xc3, 0x5d, 0xf8, 0x85, 0x7e, 0x88, 0x61, 0x5a, 0xbb, + 0xe6, 0x8e, 0xbc, 0x00, 0xe1, 0xd7, 0xfb, 0x39, 0xe1, 0x85, 0xe8, 0xeb, + 0x6d, 0x9d, 0x48, 0x7b, 0xfd, 0x1b, 0xfc, 0xc6, 0xf9, 0xae, 0xed, 0x34, + 0x5b, 0xf7, 0xb6, 0xdf, 0xc7, 0x5f, 0xdf, 0x7c, 0xed, 0x7e, 0x1d, 0x5c, + 0x3f, 0x95, 0x96, 0xfe, 0x3d, 0x7d, 0x82, 0x93, 0x1d, 0x7e, 0xf4, 0xb5, + 0xf7, 0x47, 0x5e, 0xd7, 0x42, 0x75, 0xfb, 0xef, 0x86, 0x3f, 0x3a, 0x96, + 0x78, 0xbb, 0x07, 0x2f, 0xfe, 0xf6, 0x93, 0x50, 0x39, 0xee, 0xa1, 0xd7, + 0x87, 0x3a, 0x75, 0x2c, 0xf6, 0xf6, 0x20, 0xdf, 0x83, 0x0a, 0xe0, 0x59, + 0xd7, 0xfc, 0xfa, 0x8c, 0x10, 0xf6, 0x0e, 0xbf, 0xfb, 0x17, 0xcc, 0xdf, + 0xa2, 0xea, 0xf3, 0x9d, 0x76, 0xb5, 0xc3, 0xfc, 0x13, 0x5a, 0x84, 0xdd, + 0xb1, 0xfd, 0x09, 0x1e, 0x14, 0xd7, 0xce, 0x83, 0xe3, 0xaf, 0x72, 0x3c, + 0x75, 0xfd, 0x33, 0x87, 0xa8, 0xb3, 0xaf, 0xef, 0x26, 0x06, 0x16, 0x75, + 0x78, 0xf6, 0x19, 0x2d, 0xbb, 0x42, 0x75, 0xfd, 0xbe, 0xa1, 0xb8, 0xb3, + 0xab, 0x88, 0xd8, 0x77, 0x3d, 0x11, 0x80, 0x56, 0xfb, 0xaa, 0x05, 0x67, + 0x5d, 0x92, 0x3a, 0xb0, 0xdc, 0x09, 0x1d, 0x2b, 0x6b, 0xbb, 0x91, 0x09, + 0xc9, 0x11, 0x85, 0xdf, 0x21, 0x50, 0x86, 0x1c, 0x20, 0xec, 0x7c, 0xbf, + 0x9f, 0x8c, 0x3d, 0xfc, 0xe9, 0x7f, 0x3e, 0xec, 0x2d, 0xfc, 0x75, 0x30, + 0x8e, 0x01, 0x85, 0x95, 0xfc, 0x16, 0x35, 0xed, 0x6e, 0x75, 0xca, 0xca, + 0xb6, 0x75, 0xe5, 0xbe, 0xe7, 0x5d, 0xb1, 0x0e, 0xbe, 0xe7, 0x33, 0xe9, + 0xd7, 0xed, 0x4f, 0x8c, 0xb0, 0xac, 0x1f, 0xb4, 0x10, 0x4c, 0x38, 0xe2, + 0xf5, 0x09, 0x83, 0x24, 0x29, 0xaf, 0xff, 0xff, 0x23, 0x5f, 0x8f, 0xd9, + 0x67, 0xb0, 0x3a, 0x75, 0xe7, 0x27, 0x8d, 0xce, 0xbf, 0x71, 0xae, 0xed, + 0x34, 0x52, 0x97, 0xff, 0xcf, 0xe1, 0xc9, 0xf9, 0x1d, 0x4e, 0xe7, 0x0e, + 0xbc, 0xf2, 0x62, 0x11, 0xed, 0x8e, 0xdf, 0x99, 0xdf, 0xf4, 0x98, 0xce, + 0x35, 0xdd, 0xa6, 0x89, 0x3a, 0xcc, 0x2d, 0x10, 0xce, 0x83, 0x51, 0x08, + 0xd0, 0x09, 0xe7, 0x05, 0x25, 0x1b, 0xd0, 0x6f, 0x8b, 0x93, 0x21, 0xdc, + 0xd8, 0xd1, 0xd2, 0x10, 0x4a, 0xf0, 0xa0, 0x98, 0x9f, 0x90, 0xb6, 0x5d, + 0x67, 0xa7, 0xd8, 0xcb, 0x1c, 0xa7, 0xf8, 0x64, 0x8c, 0x24, 0x75, 0x3d, + 0xbd, 0xe8, 0xcb, 0xb6, 0x47, 0x47, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x87, + 0xef, 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x25, 0x3b, 0x31, 0x87, + 0xfa, 0xb3, 0x3b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x44, 0xf7, 0xf4, + 0xc9, 0xed, 0x01, 0x67, 0x5f, 0xfe, 0x55, 0x94, 0x65, 0x5e, 0x70, 0xaa, + 0xbe, 0x7c, 0xee, 0xd9, 0xd7, 0xee, 0x35, 0xdd, 0xa6, 0x88, 0xc6, 0xff, + 0xfd, 0xfc, 0xa7, 0x55, 0xa1, 0x5b, 0x9d, 0xbc, 0xf9, 0xf3, 0xbb, 0x67, + 0x5f, 0x26, 0xf2, 0x56, 0xce, 0xb3, 0x10, 0x9a, 0xac, 0x8b, 0xb1, 0x8b, + 0xa6, 0x7e, 0x6b, 0xbf, 0xfc, 0xc2, 0xde, 0x4c, 0x67, 0x1a, 0xee, 0xd3, + 0x44, 0xf3, 0x7f, 0x31, 0xfc, 0x0c, 0xb4, 0x75, 0x42, 0xa9, 0x19, 0xca, + 0x25, 0x1c, 0xa7, 0x54, 0x3c, 0xaf, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x88, + 0x2f, 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x25, 0x4b, 0x31, 0x87, + 0xfa, 0xb3, 0x3b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x45, 0x17, 0xf9, + 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x8c, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x13, + 0x2d, 0xfa, 0x59, 0xe7, 0x69, 0xd7, 0xe6, 0x16, 0xf2, 0x63, 0x0f, 0x67, + 0x73, 0x3b, 0xf7, 0x1a, 0xee, 0xd3, 0x45, 0x49, 0x61, 0x3a, 0xdf, 0x4e, + 0xb3, 0x18, 0x7a, 0x8a, 0xe6, 0x60, 0x0f, 0xbf, 0xcc, 0x67, 0x1a, 0xee, + 0xd3, 0x45, 0x75, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8b, 0x16, 0xff, + 0xe5, 0xbc, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, 0xea, 0xff, 0x99, 0x61, + 0xe1, 0x36, 0xd3, 0x68, 0xeb, 0xff, 0xf4, 0xc3, 0x0b, 0x63, 0x34, 0x8c, + 0x85, 0xdd, 0x43, 0xae, 0xd7, 0x8e, 0xbf, 0x0b, 0xac, 0x60, 0xeb, 0xf8, + 0x1a, 0xeb, 0xc9, 0x85, 0x6c, 0xdd, 0x7d, 0x16, 0xbf, 0x67, 0xb4, 0x8b, + 0x3a, 0xff, 0xf4, 0x6f, 0xec, 0x99, 0x39, 0xed, 0x01, 0x5c, 0xeb, 0xcf, + 0xbb, 0x02, 0x7e, 0x9e, 0x26, 0xb7, 0xb1, 0x38, 0x4e, 0x42, 0x43, 0x50, + 0xc0, 0xa6, 0x15, 0x29, 0x42, 0x82, 0x47, 0x85, 0x7e, 0x4e, 0x8b, 0xcc, + 0x75, 0xfa, 0x58, 0x1f, 0x98, 0x75, 0x2a, 0x0f, 0x3a, 0x09, 0xaf, 0xd9, + 0xe4, 0x06, 0x8e, 0xb9, 0x58, 0x56, 0xa7, 0x52, 0xb5, 0x3c, 0x75, 0x58, + 0x9a, 0xfc, 0xab, 0x95, 0x8d, 0x73, 0xc7, 0x5f, 0xef, 0xa3, 0x9c, 0xe4, + 0x34, 0xea, 0x56, 0x0f, 0x99, 0x54, 0x67, 0x7d, 0xc5, 0xfb, 0x73, 0xaf, + 0xe5, 0x61, 0x59, 0x54, 0x44, 0x96, 0x75, 0xe6, 0xe7, 0x4a, 0xbc, 0xb8, + 0xd1, 0xd7, 0xbf, 0xe4, 0x1d, 0x7f, 0x67, 0xe9, 0x32, 0x32, 0x75, 0xff, + 0x9f, 0x5f, 0x35, 0xac, 0x94, 0xa0, 0xeb, 0xff, 0xf0, 0xba, 0x89, 0xc8, + 0x94, 0xb3, 0x5f, 0xff, 0x07, 0x50, 0x51, 0x84, 0xa1, 0x77, 0x4f, 0xef, + 0xff, 0xee, 0x26, 0xd3, 0xad, 0x88, 0xe7, 0x13, 0x69, 0xa0, 0x9c, 0xeb, + 0xe4, 0xef, 0xd5, 0x9d, 0x7f, 0xf9, 0x14, 0xf9, 0x82, 0xfb, 0xe9, 0x45, + 0x1c, 0xea, 0x69, 0xf8, 0x09, 0x1d, 0xff, 0xe7, 0xd0, 0xe7, 0xec, 0x75, + 0x1a, 0xfc, 0x3a, 0xfe, 0x0e, 0x29, 0xec, 0x69, 0xd7, 0xdd, 0x85, 0xb4, + 0xea, 0x73, 0xce, 0xf1, 0x6d, 0xf8, 0x29, 0x32, 0x32, 0x75, 0xff, 0xdf, + 0x22, 0x06, 0x17, 0xf3, 0xe7, 0x76, 0xce, 0xa8, 0x3f, 0x31, 0x28, 0xbf, + 0xf7, 0x72, 0x6e, 0xa7, 0x63, 0x90, 0x75, 0xcf, 0xb9, 0xd7, 0xf9, 0xf4, + 0xfd, 0x00, 0xce, 0x75, 0x09, 0xe4, 0x00, 0x5a, 0xa7, 0x5c, 0x0e, 0x90, + 0xda, 0x43, 0x7b, 0x86, 0x2b, 0x86, 0x97, 0x48, 0x46, 0x12, 0xfe, 0x84, + 0xa7, 0xd2, 0x0d, 0xa8, 0x42, 0xde, 0x17, 0xf1, 0xd7, 0x85, 0x34, 0x75, + 0x99, 0x54, 0x1b, 0x48, 0x1a, 0xbe, 0xe6, 0xc7, 0x59, 0xd7, 0xe5, 0x8b, + 0xfb, 0x47, 0x5e, 0x8c, 0xe1, 0xd7, 0xff, 0x9a, 0xfc, 0x7f, 0x26, 0xa0, + 0x63, 0xf3, 0xad, 0x2e, 0x9f, 0x0f, 0xd1, 0xaa, 0xdd, 0x16, 0x3c, 0x84, + 0x3d, 0x62, 0x65, 0x08, 0x56, 0x08, 0x6a, 0x5e, 0xd6, 0xd6, 0xd1, 0xd7, + 0xfd, 0xd7, 0xf4, 0x4d, 0xa4, 0x59, 0xd7, 0xfa, 0x24, 0x39, 0xbf, 0xb0, + 0xeb, 0xdd, 0x02, 0xce, 0xac, 0x45, 0x3a, 0x11, 0x70, 0xe0, 0x06, 0x37, + 0xf7, 0xb5, 0x34, 0x0c, 0xe7, 0x5f, 0x85, 0x44, 0xcd, 0x1d, 0x7e, 0x65, + 0xfc, 0xed, 0x3a, 0xff, 0xec, 0x65, 0xff, 0xc6, 0xf5, 0xff, 0xd1, 0xd7, + 0xfe, 0xd3, 0xef, 0x02, 0xe1, 0xc5, 0x0e, 0xa4, 0x46, 0x7f, 0x49, 0x84, + 0x9f, 0xc8, 0xb7, 0x47, 0x4e, 0xb0, 0x4e, 0xa5, 0x9a, 0x51, 0x15, 0xbe, + 0x10, 0xfc, 0x50, 0xeb, 0xfb, 0x34, 0xcb, 0x8c, 0xe7, 0x56, 0x1f, 0x8b, + 0x90, 0x09, 0x25, 0xf8, 0x0a, 0x68, 0x30, 0x75, 0xe5, 0xa6, 0x8e, 0xbf, + 0xa3, 0x79, 0x69, 0x04, 0xea, 0x85, 0x4d, 0x39, 0x0f, 0xd4, 0x86, 0x8f, + 0x4b, 0x1c, 0xa0, 0x46, 0xef, 0xff, 0x28, 0xf9, 0xbf, 0xbd, 0x19, 0xb1, + 0x1a, 0x75, 0xfe, 0x1c, 0xd7, 0x9d, 0xc4, 0xea, 0x50, 0xfe, 0xb6, 0x25, + 0xdf, 0xff, 0xf9, 0x39, 0xc8, 0xfb, 0xe4, 0x10, 0x4b, 0x34, 0x10, 0x3f, + 0x24, 0x75, 0xff, 0xfc, 0x38, 0xa6, 0x0f, 0xcd, 0x7b, 0xb8, 0xbf, 0xb1, + 0xf9, 0xd5, 0x08, 0xca, 0xc6, 0xcb, 0xfc, 0x07, 0xd2, 0x4c, 0x8c, 0x9d, + 0x48, 0x9a, 0x1f, 0x61, 0xde, 0x24, 0x37, 0xbb, 0x02, 0x75, 0xed, 0xfc, + 0xb3, 0xa9, 0xa6, 0xdd, 0xc6, 0xaf, 0xd3, 0x87, 0x88, 0xc9, 0xd7, 0xfb, + 0xeb, 0xec, 0x49, 0x91, 0x93, 0xaf, 0xfe, 0x41, 0xc0, 0x72, 0x75, 0xc6, + 0x78, 0xea, 0x83, 0xf9, 0x09, 0xbd, 0xfc, 0x17, 0xe7, 0xfb, 0x78, 0x75, + 0xee, 0xfd, 0xd8, 0x75, 0xff, 0x42, 0xc7, 0x1b, 0xc4, 0xfc, 0xea, 0x91, + 0xeb, 0xe8, 0x82, 0xff, 0xa2, 0x58, 0x9a, 0xd0, 0x20, 0xeb, 0xff, 0x7a, + 0x17, 0xbb, 0x53, 0x7c, 0xe1, 0xd7, 0xee, 0xe7, 0x13, 0x47, 0x5e, 0x14, + 0x96, 0xe7, 0xcb, 0xe3, 0xfb, 0xff, 0x3e, 0x7f, 0x02, 0xe1, 0xc5, 0x0e, + 0xa9, 0xd3, 0x0a, 0x94, 0x26, 0xff, 0x33, 0xbf, 0xcf, 0xbe, 0xbd, 0xec, + 0x57, 0x3a, 0xff, 0xf2, 0x73, 0xaf, 0x8d, 0x0e, 0x73, 0xf4, 0x3a, 0xfe, + 0x53, 0xd1, 0x82, 0xd3, 0xaf, 0xff, 0x46, 0x6f, 0xee, 0xc7, 0x86, 0x3f, + 0xd1, 0xd7, 0x47, 0xe7, 0x5d, 0xd5, 0x9d, 0x4d, 0x35, 0x9a, 0x16, 0xa4, + 0x46, 0x17, 0x8b, 0x00, 0xeb, 0x7a, 0x74, 0xe1, 0xd7, 0xf0, 0x35, 0xed, + 0x67, 0x8e, 0xbf, 0x80, 0xa9, 0x49, 0x91, 0x93, 0xae, 0xce, 0x9d, 0x79, + 0x96, 0x59, 0x2a, 0xff, 0xf7, 0x93, 0xda, 0xea, 0x6d, 0xfd, 0xe4, 0x48, + 0xa6, 0x0b, 0xfa, 0x51, 0x30, 0xd4, 0x1c, 0x72, 0xdf, 0x19, 0x00, 0xd2, + 0xff, 0xff, 0x93, 0xd2, 0x81, 0xcf, 0x75, 0x33, 0xd0, 0xb4, 0xe4, 0x8e, + 0xa9, 0x2f, 0x30, 0x85, 0xaf, 0x08, 0x1b, 0x0a, 0x24, 0x21, 0x9a, 0x10, + 0xfc, 0x8c, 0xb1, 0x67, 0x1d, 0x36, 0x18, 0xc2, 0xbd, 0x19, 0xe6, 0xc4, + 0xab, 0xfe, 0xde, 0x5a, 0xd6, 0x05, 0xfc, 0x75, 0xb0, 0xeb, 0xee, 0x0b, + 0xec, 0x3a, 0xa0, 0xfa, 0x94, 0x39, 0x40, 0xfb, 0x39, 0xd7, 0xa3, 0xba, + 0x3a, 0xb7, 0x35, 0x48, 0x1f, 0x7f, 0xff, 0x3f, 0x93, 0xae, 0xbf, 0x99, + 0xa8, 0xce, 0x60, 0x9d, 0x7f, 0xf9, 0x1b, 0xa8, 0xdb, 0xcf, 0x4a, 0x59, + 0xa3, 0xab, 0x88, 0xc4, 0x12, 0x1d, 0x8b, 0x17, 0xdc, 0xee, 0x09, 0xd4, + 0x87, 0xa2, 0xe6, 0x37, 0xde, 0x8d, 0xd9, 0x3a, 0xba, 0x78, 0x6c, 0x90, + 0x5c, 0xcf, 0x4e, 0xbf, 0xfd, 0x02, 0xdf, 0xbc, 0x7f, 0xd3, 0xdd, 0x83, + 0xaf, 0xf2, 0x33, 0xac, 0xc1, 0x9c, 0xeb, 0xe8, 0xd4, 0x6c, 0x3a, 0xff, + 0xe8, 0x17, 0xf4, 0xa1, 0x47, 0x67, 0xc7, 0x57, 0x4f, 0x94, 0x04, 0x57, + 0xbe, 0x3b, 0x4e, 0xa6, 0xa6, 0x6f, 0xf8, 0xbe, 0x92, 0xbd, 0x09, 0x7d, + 0xa2, 0x2b, 0xe5, 0xfd, 0x81, 0x3a, 0xf9, 0x03, 0x8b, 0x3a, 0xf9, 0xdc, + 0x7f, 0x3a, 0xcc, 0xc1, 0xe0, 0x28, 0x41, 0x70, 0x16, 0x75, 0xfe, 0x65, + 0xe6, 0xc9, 0x42, 0xb9, 0xd4, 0x87, 0xeb, 0xd2, 0x9d, 0x0b, 0x5f, 0xe8, + 0x7e, 0x75, 0x97, 0x09, 0x57, 0x32, 0xc9, 0x54, 0x13, 0xca, 0x64, 0xca, + 0xf7, 0x91, 0x5c, 0xa6, 0x0d, 0x1d, 0xfd, 0xbb, 0x53, 0x5d, 0x43, 0xaf, + 0x81, 0x20, 0x78, 0xea, 0x44, 0xfc, 0x26, 0x86, 0xbe, 0xa1, 0x37, 0xe2, + 0xfd, 0xb2, 0xdb, 0x99, 0xd1, 0xd6, 0xc3, 0xad, 0xbe, 0x1a, 0x6f, 0x0b, + 0xdf, 0x6f, 0x25, 0x46, 0xe7, 0x5f, 0xfd, 0xad, 0x04, 0x60, 0x3d, 0x8f, + 0x68, 0xea, 0x84, 0x49, 0x61, 0x38, 0x0a, 0x2f, 0xfd, 0xe4, 0xe3, 0xff, + 0xb5, 0xec, 0xe9, 0xd7, 0xfc, 0x8c, 0x8e, 0x79, 0x01, 0xf9, 0xd7, 0xf9, + 0xf9, 0xed, 0x0a, 0x28, 0x75, 0xff, 0xed, 0x62, 0x98, 0x0e, 0x38, 0x63, + 0xb0, 0x75, 0x49, 0x32, 0x14, 0x2e, 0x57, 0x41, 0x73, 0x8d, 0x19, 0x5e, + 0xc4, 0xe1, 0xd7, 0xfa, 0x48, 0xbe, 0xee, 0xea, 0xe7, 0x5f, 0x3f, 0x22, + 0x47, 0x5f, 0xf3, 0xef, 0xf3, 0x7d, 0x60, 0xa8, 0x75, 0x4e, 0x8a, 0xcd, + 0xc6, 0x96, 0x6d, 0xe2, 0x0b, 0xee, 0xab, 0xa2, 0xce, 0xbc, 0x31, 0xf9, + 0xd7, 0xa1, 0x79, 0xf0, 0xdf, 0xe8, 0x92, 0xff, 0xd1, 0xbf, 0x61, 0x6d, + 0xea, 0x4c, 0x75, 0x62, 0x3c, 0x11, 0xfb, 0x86, 0x77, 0xe6, 0xbc, 0xf8, + 0xc9, 0xd7, 0xe8, 0xe0, 0x70, 0x4e, 0xa1, 0x3c, 0xdf, 0x14, 0x5f, 0xfd, + 0x1f, 0xc7, 0x56, 0x2e, 0xa7, 0x50, 0xeb, 0x2a, 0x8e, 0xbf, 0xc1, 0xec, + 0x0b, 0x2f, 0xb9, 0xd7, 0xff, 0x20, 0x7b, 0x0d, 0x8f, 0xdc, 0x7f, 0x3a, + 0xff, 0xff, 0x96, 0xe3, 0xbc, 0x98, 0x67, 0x13, 0x66, 0x0e, 0x05, 0xe4, + 0x78, 0xbd, 0x6f, 0xca, 0x79, 0xdc, 0x4e, 0xbc, 0x20, 0x9c, 0xea, 0x73, + 0xc2, 0xf1, 0x35, 0x22, 0x35, 0xc6, 0x16, 0xd5, 0x09, 0xf5, 0xf0, 0x85, + 0x68, 0x6e, 0x29, 0xa3, 0x30, 0x46, 0x35, 0x72, 0xb0, 0xad, 0x9d, 0x79, + 0x23, 0x87, 0x52, 0xa8, 0xdd, 0x74, 0x82, 0xff, 0xee, 0x22, 0xe1, 0x5c, + 0x71, 0x7b, 0xc1, 0xd5, 0x23, 0xea, 0x98, 0x96, 0xf9, 0x05, 0xc2, 0x75, + 0xe9, 0xd6, 0x87, 0x50, 0x4d, 0xd8, 0x8f, 0xdf, 0xa5, 0x9b, 0x22, 0x47, + 0x5e, 0xce, 0x41, 0xd5, 0xba, 0x30, 0x11, 0x7b, 0x84, 0x1d, 0x28, 0xbf, + 0xfe, 0xcf, 0x6b, 0x26, 0xec, 0x6c, 0xce, 0xf6, 0x0e, 0xbf, 0xff, 0xff, + 0x26, 0x6f, 0xa4, 0xc6, 0x7e, 0x66, 0xf2, 0xd2, 0x7b, 0x49, 0xb8, 0x42, + 0x09, 0xce, 0xbf, 0xff, 0x20, 0x87, 0xe7, 0xdf, 0x26, 0x9d, 0x04, 0x12, + 0x3a, 0x85, 0x32, 0xef, 0x28, 0x6c, 0x84, 0x45, 0xe0, 0x72, 0x47, 0x5f, + 0xcf, 0xef, 0xfe, 0x8c, 0x8e, 0xaf, 0x87, 0x97, 0x38, 0xe5, 0xfe, 0x89, + 0x23, 0x0c, 0xb2, 0xc9, 0x57, 0x94, 0xc0, 0x9d, 0x7f, 0x75, 0xf8, 0xd8, + 0xf1, 0xd7, 0x38, 0x4e, 0xbf, 0xb8, 0xfa, 0xeb, 0xc8, 0xeb, 0x6e, 0x75, + 0xc8, 0xc9, 0xd7, 0x7d, 0xfc, 0xea, 0x98, 0xd7, 0xfe, 0x2d, 0x7a, 0x4e, + 0x13, 0xae, 0x65, 0x93, 0xaa, 0x48, 0xd7, 0xc1, 0x56, 0x96, 0x22, 0x06, + 0x88, 0xd9, 0x1b, 0xbd, 0xef, 0xbf, 0x94, 0xc1, 0xeb, 0x5f, 0xf2, 0x07, + 0x16, 0x93, 0x23, 0x27, 0x5f, 0xfe, 0x70, 0xe6, 0x0a, 0x9a, 0xd6, 0x0f, + 0xe7, 0x5f, 0x74, 0x0e, 0xa4, 0x22, 0x01, 0x67, 0x17, 0xff, 0xf4, 0x9f, + 0x5a, 0x8c, 0x9c, 0x12, 0x0f, 0x05, 0xd9, 0x3a, 0xef, 0x40, 0x51, 0x2a, + 0x87, 0x57, 0xed, 0x3c, 0xfa, 0xe9, 0xd5, 0x25, 0x62, 0x01, 0x1c, 0xde, + 0x35, 0x94, 0x8d, 0x1b, 0xc5, 0xb7, 0xed, 0x9f, 0x7a, 0x9e, 0x3a, 0xff, + 0xb3, 0xdd, 0x8e, 0x7b, 0x1a, 0x75, 0xe8, 0xe4, 0xc7, 0x54, 0x2f, 0x17, + 0x64, 0x6d, 0x69, 0x08, 0x2e, 0x92, 0xbc, 0xb4, 0x6f, 0xd6, 0x04, 0xaf, + 0x6c, 0xde, 0xf6, 0x9e, 0x63, 0xaf, 0xfe, 0x40, 0xbf, 0x93, 0x59, 0x2c, + 0xe9, 0xd7, 0x3e, 0xd1, 0xd6, 0xce, 0x9e, 0xcf, 0x90, 0x6b, 0x74, 0x4e, + 0x0b, 0xad, 0xf6, 0x6f, 0x3e, 0xc3, 0xaf, 0xf8, 0x43, 0x82, 0x09, 0x66, + 0x8e, 0xbf, 0xdf, 0x7c, 0x39, 0x3a, 0x70, 0xeb, 0xef, 0x26, 0x90, 0xea, + 0xe2, 0x2b, 0xdc, 0x94, 0x4d, 0x80, 0x69, 0x7f, 0xdd, 0x40, 0xa2, 0xa6, + 0x05, 0x0e, 0xbf, 0xcf, 0x2c, 0x0f, 0x35, 0xa3, 0xaf, 0xa3, 0x3e, 0x84, + 0xeb, 0xfc, 0xa2, 0x79, 0xfa, 0xca, 0xb9, 0xd7, 0xfd, 0xcc, 0x9b, 0xb9, + 0xa7, 0x13, 0xaf, 0xfb, 0xb9, 0x2c, 0x02, 0xa5, 0xc4, 0xeb, 0xff, 0xfc, + 0x83, 0x9b, 0xf9, 0x47, 0xf7, 0x63, 0xb9, 0xb1, 0xe4, 0x75, 0x05, 0x35, + 0xd6, 0x99, 0x21, 0x17, 0x0d, 0xfc, 0x6f, 0xb0, 0xea, 0xff, 0x82, 0x9c, + 0x8d, 0x9f, 0xea, 0x47, 0x5d, 0x0b, 0x3a, 0xde, 0x83, 0xd0, 0xe9, 0xdd, + 0xff, 0xa3, 0x4f, 0xd4, 0x0b, 0x52, 0x73, 0xaa, 0x15, 0x51, 0xe4, 0x72, + 0xcf, 0x0a, 0x90, 0x13, 0xde, 0x81, 0xf1, 0xd7, 0xf9, 0x3a, 0x9c, 0x94, + 0xd0, 0x75, 0xff, 0xf9, 0x00, 0xdf, 0xbb, 0xfe, 0xfa, 0x7e, 0x26, 0xff, + 0x9d, 0x7c, 0xfc, 0x89, 0x1d, 0x7f, 0xff, 0x20, 0xba, 0x0f, 0xfc, 0x8e, + 0xba, 0x7a, 0x3a, 0x75, 0x09, 0xfb, 0x78, 0x82, 0xfc, 0x9e, 0xd0, 0x27, + 0x3a, 0xff, 0xfa, 0x05, 0x3f, 0xf6, 0xed, 0x4e, 0x7d, 0x80, 0x9d, 0x41, + 0x4d, 0xa9, 0x21, 0xa0, 0xb2, 0x1f, 0x14, 0x5f, 0xb8, 0x06, 0xf6, 0x0e, + 0xbf, 0xb9, 0x34, 0x93, 0xda, 0x3a, 0xc3, 0x07, 0xab, 0x84, 0xf7, 0xfa, + 0x67, 0x99, 0xf7, 0x96, 0x8e, 0xbf, 0x9e, 0x74, 0x99, 0x19, 0x3a, 0xb0, + 0xf8, 0xdc, 0xd6, 0xfe, 0x9f, 0x06, 0x7c, 0x64, 0xeb, 0xfe, 0x89, 0xfe, + 0xcb, 0xa0, 0x79, 0xce, 0xac, 0x3e, 0xae, 0x17, 0x5f, 0xa3, 0x9c, 0xce, + 0x9d, 0x7f, 0x0b, 0xa9, 0x0b, 0x83, 0xaa, 0x47, 0xa2, 0x02, 0x6b, 0xe8, + 0x9d, 0x45, 0x0e, 0xbf, 0xff, 0x23, 0x61, 0x7a, 0x7e, 0x62, 0xc0, 0xd7, + 0x91, 0xd7, 0x26, 0xc3, 0xad, 0xd3, 0xaa, 0x47, 0xf4, 0xae, 0xa6, 0x01, + 0x7b, 0xc1, 0x85, 0x9d, 0x7f, 0xb3, 0xfc, 0x9a, 0x37, 0xd1, 0xd5, 0x07, + 0x9f, 0x83, 0x77, 0xf7, 0x5e, 0x51, 0xa9, 0x1d, 0x7f, 0xd9, 0xd4, 0xdf, + 0x5d, 0x06, 0x8e, 0xbb, 0x05, 0xa7, 0xcb, 0xf9, 0x65, 0xfc, 0x2f, 0xf8, + 0x70, 0x4e, 0xbf, 0x26, 0xde, 0x71, 0x43, 0xae, 0x52, 0x47, 0x5f, 0xba, + 0x9b, 0x11, 0xa7, 0x5d, 0x9d, 0x91, 0xbf, 0x68, 0xbd, 0x2d, 0x12, 0xbb, + 0x6d, 0x37, 0x99, 0x65, 0x92, 0xaf, 0xfd, 0xc1, 0x03, 0xfd, 0xc9, 0xa1, + 0x67, 0x30, 0x5f, 0xdf, 0xba, 0x93, 0x23, 0x27, 0x54, 0x1f, 0xbe, 0x27, + 0xdf, 0xe8, 0x0e, 0x4a, 0x05, 0xa7, 0x54, 0x2f, 0xc8, 0x48, 0x6b, 0x23, + 0x9c, 0x57, 0x84, 0xbc, 0xd0, 0x88, 0xe4, 0x22, 0x96, 0xe5, 0xd2, 0x27, + 0x84, 0xf0, 0xc2, 0x07, 0x50, 0x85, 0xf1, 0x68, 0x21, 0x80, 0xcc, 0x2f, + 0x3e, 0x90, 0x5f, 0x73, 0x99, 0xd3, 0xaf, 0xee, 0xa6, 0xd6, 0xd0, 0x14, + 0x3a, 0xa0, 0xf5, 0x5a, 0x43, 0x65, 0x49, 0xd6, 0x43, 0xaf, 0xfb, 0xd1, + 0xcd, 0x76, 0x07, 0xc7, 0x59, 0x52, 0x75, 0xff, 0x7a, 0x39, 0xae, 0xc0, + 0xf8, 0xeb, 0xb5, 0x07, 0x5e, 0x58, 0x60, 0xeb, 0xfc, 0x3e, 0x79, 0xb5, + 0x1e, 0x3a, 0x90, 0xf3, 0x5c, 0x6e, 0xf9, 0x1f, 0x1a, 0x75, 0xff, 0xb3, + 0x60, 0xe6, 0xa6, 0x18, 0x09, 0xd7, 0xcd, 0x0c, 0x4e, 0x75, 0xdf, 0xc1, + 0xd7, 0xb4, 0x9c, 0x3a, 0xb0, 0xf4, 0xff, 0x22, 0xf0, 0xb5, 0xfe, 0x96, + 0x0a, 0x07, 0x04, 0xeb, 0xde, 0xd3, 0x10, 0x9e, 0xde, 0x0a, 0x4c, 0x6f, + 0xd6, 0x2f, 0xc8, 0x04, 0x7f, 0x50, 0x91, 0xf1, 0x7d, 0xda, 0x83, 0xaf, + 0x2c, 0x30, 0x75, 0xfe, 0x1f, 0x3c, 0xda, 0x8f, 0x1d, 0x48, 0x79, 0xae, + 0x37, 0x7c, 0x8f, 0x8d, 0x3a, 0xff, 0xd9, 0xb0, 0x73, 0x53, 0x0c, 0x04, + 0xeb, 0xe6, 0x86, 0x27, 0x3a, 0xfe, 0x9b, 0xf4, 0x57, 0x79, 0x8e, 0xbb, + 0xf8, 0x3a, 0xf6, 0x93, 0x87, 0x56, 0x22, 0x15, 0xa4, 0x5f, 0x99, 0x78, + 0x5a, 0xff, 0x4b, 0x05, 0x03, 0x82, 0x75, 0xfc, 0x2e, 0x1c, 0x51, 0x88, + 0x5c, 0x8e, 0x08, 0xa6, 0x07, 0xb6, 0x50, 0x94, 0xd0, 0x89, 0xeb, 0x17, + 0xe4, 0x02, 0x3f, 0xa8, 0x61, 0xf8, 0xf6, 0xff, 0xee, 0x46, 0xfa, 0x18, + 0x5e, 0x6f, 0xe3, 0xaf, 0xff, 0xce, 0x1c, 0xc1, 0x53, 0xe8, 0xc0, 0xce, + 0x9c, 0x3a, 0xf3, 0xf2, 0x73, 0xc8, 0x25, 0x7d, 0x2c, 0xde, 0x47, 0x90, + 0x4a, 0xf6, 0x90, 0x27, 0x90, 0x4a, 0xe6, 0x59, 0x3c, 0x82, 0x54, 0xd4, + 0x52, 0xcc, 0x53, 0xe2, 0xf6, 0x4a, 0x2e, 0x7f, 0x16, 0x41, 0x23, 0x06, + 0xfe, 0xfe, 0xce, 0xe6, 0x0a, 0x87, 0x5e, 0x71, 0xff, 0xe2, 0xfa, 0x5c, + 0x4e, 0x57, 0xf2, 0x18, 0x2b, 0x44, 0x18, 0xce, 0x3c, 0x69, 0x7d, 0xb7, + 0x8f, 0xd3, 0xad, 0x8a, 0xe8, 0xa1, 0xfd, 0xfa, 0xd2, 0x3a, 0xff, 0x4d, + 0x20, 0x4f, 0xe4, 0x9c, 0xab, 0x41, 0xd7, 0xf9, 0x24, 0x07, 0xd7, 0x50, + 0xeb, 0xfb, 0x36, 0x3a, 0xf3, 0xa7, 0x5a, 0x45, 0x5e, 0x7e, 0x4e, 0x55, + 0x15, 0x50, 0x6d, 0x9a, 0x20, 0xb1, 0xcb, 0xd1, 0xfb, 0x4a, 0x60, 0xd6, + 0xd2, 0xd1, 0x7a, 0x30, 0x90, 0xa8, 0x4c, 0x57, 0x21, 0xdd, 0x7f, 0xfd, + 0xf4, 0x65, 0xae, 0x87, 0x39, 0xfa, 0xd3, 0x47, 0x5f, 0x01, 0xf9, 0x23, + 0xac, 0xb3, 0xae, 0xc9, 0x04, 0xd8, 0xcc, 0x43, 0x7e, 0x67, 0x26, 0x45, + 0x9d, 0x7f, 0x36, 0x26, 0x94, 0x7e, 0x55, 0x90, 0xeb, 0xfe, 0x9c, 0x12, + 0x0f, 0x40, 0xe2, 0x75, 0xfc, 0x90, 0xb9, 0xf1, 0x93, 0xaf, 0xd9, 0x3a, + 0xf1, 0x67, 0x5e, 0xd2, 0x70, 0xea, 0x13, 0xc2, 0xf1, 0x3d, 0xfc, 0x2f, + 0xff, 0xe0, 0xd1, 0xd7, 0xf2, 0x29, 0xf6, 0x16, 0xc0, 0x53, 0x06, 0xc0, + 0xfe, 0x1c, 0xe9, 0xbf, 0xc4, 0x35, 0x89, 0xe6, 0x21, 0x40, 0xc6, 0x69, + 0x7c, 0x39, 0x38, 0x0e, 0xbf, 0xec, 0xf7, 0xc1, 0xcf, 0xfe, 0xee, 0x75, + 0x49, 0x73, 0x2c, 0x25, 0x98, 0x21, 0xc3, 0x6e, 0xc6, 0x49, 0xf9, 0x38, + 0xc2, 0x0f, 0x51, 0xfc, 0xf8, 0xd3, 0x6c, 0x86, 0xff, 0xfd, 0x3f, 0x39, + 0x81, 0x75, 0xf5, 0xfc, 0x31, 0x31, 0xd7, 0xff, 0xff, 0x81, 0xc0, 0x4c, + 0x2f, 0xfe, 0xb5, 0x8a, 0x60, 0x38, 0xe1, 0x8e, 0xc1, 0xd7, 0xdb, 0x5d, + 0x07, 0xd3, 0xaf, 0x32, 0xcb, 0x25, 0x5d, 0x28, 0x29, 0x82, 0xfe, 0xa1, + 0x33, 0x89, 0xd5, 0x77, 0x78, 0xe2, 0x35, 0xfc, 0xa4, 0x73, 0x99, 0xd3, + 0xaf, 0xe9, 0xe6, 0x92, 0xab, 0x93, 0x9d, 0x7d, 0xd7, 0xdd, 0x93, 0xaf, + 0xd3, 0xf1, 0x21, 0x67, 0x5f, 0xff, 0x47, 0xdf, 0x0c, 0x7e, 0xfe, 0xff, + 0xe8, 0xc8, 0xea, 0x56, 0x51, 0xa4, 0x86, 0xae, 0x47, 0xe2, 0x7b, 0xff, + 0x3f, 0xb4, 0xce, 0x77, 0xf7, 0xf1, 0xd7, 0xff, 0xfe, 0xcf, 0x43, 0x47, + 0x30, 0x62, 0x5e, 0xeb, 0xac, 0x73, 0x61, 0xd4, 0x14, 0x53, 0xb2, 0x7f, + 0x7b, 0xe8, 0x66, 0x3a, 0xf4, 0x90, 0x4e, 0xbe, 0x9f, 0xee, 0xd3, 0x27, + 0x5f, 0xf4, 0x75, 0xd3, 0xd3, 0x23, 0x27, 0x5f, 0xfe, 0x52, 0x35, 0xc8, + 0xe8, 0xe7, 0xa1, 0x67, 0x5f, 0xf6, 0x87, 0x36, 0x24, 0xc8, 0xc9, 0xd7, + 0xff, 0xf0, 0x1e, 0x76, 0x82, 0x7f, 0x67, 0x47, 0x3d, 0xd4, 0x3a, 0xfd, + 0x13, 0x08, 0x34, 0x75, 0x62, 0x60, 0x88, 0x91, 0xd3, 0xaf, 0x2d, 0xdc, + 0x82, 0x75, 0xfc, 0xe3, 0xfe, 0x79, 0x43, 0xaa, 0x15, 0x1f, 0xce, 0x49, + 0x21, 0xf7, 0x1a, 0x12, 0x9f, 0x46, 0x79, 0xb0, 0xf3, 0x6c, 0x52, 0xfb, + 0xa0, 0x5c, 0x1d, 0x73, 0xe8, 0xeb, 0x80, 0xa9, 0x3a, 0x9c, 0xf4, 0x04, + 0x84, 0x02, 0xb7, 0x3b, 0x0a, 0x87, 0xca, 0x86, 0x56, 0xdb, 0x15, 0x50, + 0x93, 0x56, 0x85, 0x6a, 0xd4, 0x8d, 0x57, 0x1d, 0xc4, 0xe1, 0x4c, 0xf2, + 0x81, 0xe5, 0x0d, 0xb0, 0xca, 0xa4, 0xca, 0x43, 0xe2, 0x91, 0x97, 0x36, + 0x3b, 0x0d, 0xe3, 0x5a, 0x49, 0x48, 0x93, 0x4a, 0x31, 0xe4, 0x7d, 0x0b, + 0x94, 0xcd, 0xd9, 0xfe, 0xe7, 0x8c, 0x87, 0xf8, 0x69, 0x0c, 0xad, 0xed, + 0x4f, 0xeb, 0xfa, 0x9c, 0x18, 0x08, 0xf6, 0x59, 0x3f, 0xdb, 0x87, 0xff, + 0xd9, 0x64, 0xdb, 0x50, 0xcc, 0xbf, 0x2f, 0x11, 0xff, 0x3a, 0xf9, 0xae, + 0xed, 0x34, 0x51, 0x57, 0xff, 0xe7, 0xfe, 0x1b, 0xd4, 0xd7, 0x53, 0xdd, + 0xc1, 0x3a, 0xb8, 0x88, 0x01, 0x2d, 0xbf, 0x30, 0xb7, 0x93, 0x10, 0x8c, + 0x8c, 0x85, 0x35, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x2e, 0x8b, 0xff, + 0x98, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x5d, 0xfb, 0x8d, 0x77, + 0x69, 0xa2, 0xf2, 0xb9, 0xf6, 0x1d, 0x66, 0x30, 0xf2, 0xb6, 0xcc, 0xea, + 0x1f, 0x50, 0x3a, 0x72, 0x89, 0x1f, 0xe4, 0x26, 0x1b, 0x09, 0x59, 0x8e, + 0x16, 0x7f, 0xd9, 0x52, 0x23, 0x79, 0x61, 0x7a, 0x96, 0x3b, 0xe4, 0x50, + 0x1f, 0xec, 0x84, 0xdd, 0xff, 0xe6, 0x16, 0xf2, 0x63, 0x38, 0xd7, 0x76, + 0x9a, 0x25, 0x9b, 0x81, 0xd3, 0xaf, 0xf2, 0x07, 0xb8, 0x82, 0xa1, 0xd7, + 0xdd, 0x7f, 0x00, 0xeb, 0xee, 0xc2, 0xba, 0xce, 0xbc, 0x06, 0xb9, 0xd5, + 0x24, 0x48, 0xa1, 0x8a, 0xb9, 0x0f, 0xd2, 0x4b, 0xf8, 0x3e, 0x03, 0xcb, + 0x47, 0x5e, 0xf3, 0xac, 0xeb, 0xff, 0x76, 0x3a, 0x8a, 0x7b, 0x4f, 0xf9, + 0xd7, 0xf0, 0xfb, 0x90, 0xed, 0x3a, 0xf9, 0xae, 0xed, 0x34, 0x46, 0x77, + 0xf2, 0x42, 0xe7, 0xc6, 0x4e, 0xb8, 0x64, 0x75, 0x96, 0x75, 0xf9, 0x39, + 0xd7, 0x63, 0x87, 0xa4, 0xb2, 0xdf, 0xa2, 0xb7, 0xf3, 0xc9, 0x38, 0xfc, + 0x3a, 0xff, 0xed, 0x20, 0x35, 0x82, 0x09, 0x66, 0x8e, 0xbd, 0xa8, 0xdc, + 0xea, 0x92, 0x78, 0x18, 0x7f, 0xc2, 0xb5, 0xbf, 0x8a, 0x76, 0x8a, 0xfc, + 0x85, 0x7f, 0xdc, 0x76, 0x7a, 0x91, 0xc8, 0x3a, 0xff, 0xa5, 0xac, 0x8f, + 0x91, 0xa5, 0x9d, 0x7d, 0xbf, 0x63, 0x47, 0x5f, 0x6a, 0x3d, 0xa3, 0xab, + 0x0f, 0x0f, 0x44, 0x57, 0xff, 0x79, 0x38, 0xff, 0xfc, 0xde, 0x50, 0xb3, + 0xaf, 0xc3, 0x12, 0xd3, 0x9d, 0x48, 0x7d, 0x9b, 0x11, 0xef, 0xff, 0xff, + 0xb3, 0xde, 0x45, 0xf1, 0x33, 0x71, 0x07, 0xa3, 0xbf, 0x36, 0x27, 0xa6, + 0x83, 0xaf, 0xf3, 0xcb, 0x5a, 0x71, 0x91, 0xd7, 0xe5, 0x3d, 0xe8, 0x59, + 0xd7, 0xff, 0xbd, 0x0d, 0x4f, 0x22, 0xe6, 0xd2, 0x09, 0xd6, 0x91, 0xd4, + 0x87, 0xb1, 0xf5, 0x22, 0xfd, 0xfc, 0x7a, 0x02, 0x75, 0x22, 0x32, 0x9e, + 0x10, 0x00, 0x23, 0xbf, 0xfe, 0x07, 0xb5, 0xbc, 0xa0, 0x7f, 0xd7, 0xc0, + 0x09, 0xd7, 0xa3, 0xd0, 0x75, 0x04, 0xfb, 0x76, 0x29, 0xde, 0xee, 0x09, + 0xd4, 0x86, 0xf8, 0x04, 0x97, 0x76, 0x63, 0xaf, 0xf6, 0xfa, 0x1c, 0xe0, + 0x60, 0xea, 0x43, 0xc9, 0x71, 0x7b, 0xef, 0x74, 0x1b, 0x67, 0x5f, 0xec, + 0x8e, 0x3c, 0x93, 0xa7, 0x5f, 0xe4, 0x67, 0x51, 0xd7, 0x57, 0x3a, 0xb8, + 0x7c, 0xbe, 0x30, 0xa4, 0x45, 0x62, 0xe1, 0x15, 0x7f, 0xf9, 0x3a, 0x05, + 0x70, 0xf4, 0x1a, 0xde, 0x4e, 0x75, 0x61, 0xfa, 0xb9, 0x3d, 0xef, 0xb8, + 0xaa, 0x3a, 0xff, 0xf0, 0x3f, 0x5a, 0x0e, 0x7e, 0x38, 0xf3, 0x1d, 0x7f, + 0xd0, 0x9d, 0x48, 0x19, 0x80, 0x75, 0xff, 0x80, 0x1e, 0x60, 0x3b, 0x0b, + 0xc3, 0xab, 0x11, 0xbb, 0xc2, 0x1e, 0xa4, 0xe8, 0xda, 0xff, 0xfb, 0x79, + 0x27, 0x03, 0xd0, 0x73, 0x1b, 0xdc, 0x3a, 0xe4, 0x64, 0xeb, 0xb6, 0xb0, + 0xea, 0xd1, 0xae, 0xf0, 0xb5, 0xfd, 0xa8, 0xf6, 0xba, 0x87, 0x5f, 0x87, + 0x17, 0xcc, 0x3a, 0xfb, 0x9b, 0x30, 0x27, 0x56, 0x1f, 0xa2, 0xcb, 0x00, + 0x4b, 0x7d, 0xfa, 0x6f, 0x23, 0xaf, 0xf4, 0x0f, 0x92, 0x71, 0x83, 0xaf, + 0xff, 0x27, 0x12, 0x78, 0x1c, 0xef, 0x01, 0xb0, 0xea, 0xfd, 0x13, 0xa2, + 0x47, 0xe3, 0x0b, 0x30, 0xad, 0xb3, 0x00, 0x22, 0x14, 0xf3, 0xa0, 0x84, + 0xb7, 0x23, 0xdb, 0x51, 0x8f, 0x73, 0x74, 0x7c, 0x9a, 0x11, 0xbc, 0x23, + 0x5c, 0x20, 0x3b, 0x0f, 0xb7, 0x86, 0xf7, 0xed, 0x23, 0x1a, 0x0e, 0xa1, + 0xfb, 0xe3, 0xcd, 0x8f, 0xdb, 0x70, 0x95, 0xfb, 0x0c, 0xbb, 0xff, 0xcc, + 0x2d, 0xe4, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x4d, 0x37, 0xff, 0x98, 0x5b, + 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x9c, 0x6f, 0xff, 0x30, 0xb7, 0x93, + 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x40, 0xdf, 0xb8, 0xd7, 0x76, 0x9a, 0x2e, + 0x0b, 0xf8, 0x73, 0xcd, 0x4d, 0x1d, 0x74, 0x21, 0xd7, 0xf8, 0x65, 0x08, + 0x1c, 0x59, 0xd5, 0x88, 0xa2, 0x59, 0x9f, 0x4a, 0xc0, 0x29, 0x7e, 0x93, + 0x0a, 0x2a, 0x14, 0x3a, 0x98, 0x3e, 0xb8, 0x3c, 0xb9, 0xff, 0x3a, 0xfd, + 0x34, 0xa0, 0x64, 0x75, 0x1d, 0x58, 0x6c, 0x44, 0x9e, 0xfa, 0x3f, 0xc6, + 0x4e, 0xb9, 0x18, 0xe2, 0x22, 0x05, 0x1f, 0xe8, 0xfd, 0xff, 0x49, 0x8c, + 0xe3, 0x5d, 0xda, 0x68, 0x92, 0x6c, 0xc7, 0x51, 0x04, 0xe7, 0xb7, 0x33, + 0xf9, 0xd7, 0xf9, 0xfc, 0x39, 0x3b, 0x89, 0xd7, 0xf6, 0x0b, 0xef, 0x2d, + 0x1d, 0x7f, 0x42, 0xf9, 0x81, 0xf1, 0xd7, 0x3b, 0x01, 0x45, 0x02, 0x83, + 0x1c, 0x30, 0xd1, 0x65, 0x4e, 0xd9, 0x00, 0x4a, 0x98, 0xae, 0xd8, 0xd6, + 0x26, 0x57, 0xfd, 0x5f, 0x51, 0xb2, 0x7a, 0x32, 0xcd, 0x90, 0xc9, 0xbf, + 0xf2, 0x8e, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x5a, 0x97, 0xfe, 0x79, 0x31, + 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0xad, 0xc8, 0xc9, 0xd4, 0x75, 0x98, 0x51, + 0x16, 0xab, 0x4b, 0xf2, 0x56, 0xd0, 0xb5, 0xfd, 0x9c, 0x6b, 0xbb, 0x4d, + 0x11, 0x4d, 0xff, 0xcb, 0x63, 0xc2, 0xff, 0xeb, 0xd8, 0xd3, 0xa9, 0x83, + 0xfd, 0x73, 0x8b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x46, 0x97, 0x03, + 0xa7, 0x5f, 0xf8, 0x38, 0xb4, 0xe6, 0x6a, 0x68, 0x3a, 0xff, 0xff, 0x9c, + 0x1a, 0xee, 0x07, 0xef, 0xdd, 0x27, 0xdf, 0x26, 0xa6, 0xfa, 0x75, 0xe4, + 0x76, 0x4e, 0xa4, 0x46, 0x3a, 0xb9, 0xea, 0xdb, 0xef, 0x9a, 0xee, 0xd3, + 0x45, 0x3f, 0x77, 0xa0, 0xea, 0xe1, 0xe1, 0x78, 0xb6, 0xff, 0xde, 0x9a, + 0x3d, 0xd7, 0x9b, 0xe6, 0x1d, 0x7f, 0xf9, 0x16, 0x20, 0xea, 0x73, 0x35, + 0x34, 0x1d, 0x7f, 0xf0, 0x3d, 0xc0, 0x4d, 0xa6, 0xbc, 0xda, 0x3a, 0xff, + 0xec, 0x98, 0x03, 0x3e, 0x9a, 0xf3, 0x68, 0xeb, 0x30, 0xad, 0xaa, 0x89, + 0x88, 0x6e, 0xe3, 0xa2, 0x11, 0x3a, 0x08, 0xa4, 0x79, 0x1e, 0xff, 0xf3, + 0x0b, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x13, 0x55, 0xfe, 0x63, 0x38, + 0xd7, 0x76, 0x9a, 0x2b, 0xbb, 0xe6, 0xbb, 0xb4, 0xd1, 0x5f, 0x5e, 0x65, + 0x96, 0x4a, 0xb0, 0x94, 0xc1, 0x7f, 0x5c, 0x3e, 0xb5, 0xa6, 0x5e, 0x94, + 0x6e, 0x75, 0xe9, 0xb3, 0xa7, 0x5f, 0xfb, 0x3a, 0xcb, 0xfb, 0x51, 0x93, + 0x9d, 0x6f, 0x1d, 0x7f, 0xc9, 0xcc, 0x9d, 0x25, 0x81, 0x3a, 0xb8, 0x78, + 0xee, 0x21, 0x7e, 0xdf, 0x6b, 0xa0, 0xfa, 0x75, 0xb8, 0x75, 0x1d, 0x6e, + 0xa1, 0x75, 0xc1, 0x0b, 0x31, 0x89, 0xb6, 0xcc, 0x44, 0xe3, 0x82, 0x39, + 0xa8, 0x42, 0x80, 0x87, 0x6d, 0x22, 0xff, 0xf3, 0x0b, 0x79, 0x31, 0x9c, + 0x6b, 0xbb, 0x4d, 0x13, 0xdd, 0xfb, 0xb1, 0xb4, 0xfb, 0x9d, 0x7e, 0xe3, + 0x5d, 0xda, 0x68, 0xb8, 0x6c, 0xc4, 0x1e, 0xee, 0x15, 0x5f, 0xfc, 0xc3, + 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x93, 0xea, 0x19, 0x05, 0xb3, 0xc3, + 0x16, 0x44, 0x4a, 0x4a, 0xc8, 0x6b, 0x94, 0xca, 0xfc, 0x94, 0x2f, 0xd7, + 0x2d, 0x42, 0xd3, 0x61, 0x3d, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x22, + 0xab, 0xf7, 0x1a, 0xee, 0xd3, 0x45, 0x33, 0x7f, 0x27, 0x71, 0xf7, 0xfc, + 0xeb, 0x31, 0x87, 0xc1, 0xb6, 0x67, 0x7f, 0xf9, 0x85, 0xbc, 0x98, 0xce, + 0x35, 0xdd, 0xa6, 0x89, 0x9e, 0xff, 0xf3, 0x0b, 0x79, 0x31, 0x9c, 0x6b, + 0xbb, 0x4d, 0x14, 0x6d, 0x4e, 0x9b, 0xc0, 0x61, 0x3e, 0xa1, 0x5f, 0x95, + 0xef, 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x23, 0xab, 0xff, 0xb9, + 0x3b, 0x1a, 0x1c, 0xf6, 0xa1, 0x67, 0x53, 0x08, 0x8f, 0x84, 0xab, 0x81, + 0xd3, 0xaf, 0x9a, 0xd0, 0x34, 0xeb, 0xf6, 0x08, 0x72, 0x73, 0xaf, 0xf4, + 0x43, 0x73, 0x9c, 0xc3, 0xa9, 0x0f, 0x58, 0x49, 0xaf, 0xd9, 0xc6, 0x81, + 0x43, 0xaf, 0xfc, 0x38, 0xa3, 0xcd, 0xae, 0xc0, 0x4e, 0xbd, 0x33, 0xf8, + 0xeb, 0xe6, 0xbb, 0xb4, 0xd1, 0x4d, 0x5f, 0xb3, 0x76, 0x5f, 0xa7, 0x5f, + 0xfd, 0xac, 0x10, 0xc7, 0xc5, 0x5f, 0xb3, 0xf4, 0x3a, 0x82, 0x99, 0x22, + 0x14, 0x4c, 0x7d, 0xc1, 0xc1, 0x2d, 0xd1, 0x45, 0xff, 0xff, 0x60, 0xfb, + 0x48, 0xdc, 0x1d, 0x37, 0xa9, 0xd6, 0xfd, 0x9c, 0xeb, 0xfe, 0xd3, 0xef, + 0x93, 0x47, 0x74, 0x75, 0xdd, 0x41, 0x45, 0x07, 0x99, 0xef, 0xfe, 0x97, + 0x50, 0x67, 0xd0, 0x23, 0x93, 0x1d, 0x7f, 0xda, 0xd3, 0x53, 0x9c, 0x49, + 0xce, 0xbf, 0xf6, 0x32, 0xff, 0xbf, 0xbd, 0x9d, 0x3a, 0xff, 0xc2, 0x0f, + 0x77, 0x26, 0x94, 0x6e, 0x75, 0xa6, 0x3a, 0xfd, 0x9d, 0x71, 0x09, 0xd5, + 0x39, 0xb6, 0xfc, 0x46, 0xe8, 0x50, 0xeb, 0xf9, 0xff, 0xd2, 0xac, 0xab, + 0x2a, 0xc7, 0x5f, 0xc9, 0x0b, 0x9f, 0x19, 0x3a, 0xff, 0xfb, 0x3d, 0xdc, + 0x97, 0x1c, 0x7d, 0xd7, 0x91, 0xd7, 0x47, 0xe7, 0x5f, 0xe7, 0xde, 0x1a, + 0x8d, 0x63, 0x88, 0x90, 0x12, 0xdf, 0xa9, 0xb5, 0x89, 0xea, 0xa3, 0xaf, + 0x48, 0xc4, 0x5b, 0x50, 0xcd, 0xbf, 0x7b, 0xac, 0xbc, 0xe7, 0x59, 0x85, + 0x6d, 0x77, 0xf6, 0x05, 0x82, 0xf1, 0x91, 0xa2, 0x36, 0x1e, 0xfb, 0x96, + 0xf1, 0x14, 0x4e, 0x7d, 0x28, 0x4f, 0xea, 0x6d, 0xfb, 0x8d, 0x77, 0x69, + 0xa2, 0xaa, 0xbf, 0xf3, 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x9b, 0x6c, + 0xc6, 0x1f, 0xea, 0xcc, 0xef, 0xf3, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x5f, + 0xdf, 0xb8, 0xd7, 0x76, 0x9a, 0x2c, 0x6b, 0xb6, 0xa4, 0x75, 0x98, 0xc3, + 0xcc, 0x98, 0xce, 0xfd, 0xa6, 0xf6, 0x14, 0x3a, 0xff, 0x08, 0x25, 0x9a, + 0x7f, 0x1d, 0x77, 0x3c, 0x75, 0xff, 0x67, 0xbd, 0x9c, 0x0e, 0x09, 0xd7, + 0x94, 0x96, 0x1d, 0x66, 0x31, 0x13, 0x2e, 0x62, 0x22, 0xda, 0x36, 0xb2, + 0x30, 0x98, 0x17, 0x21, 0x83, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xb5, 0x6f, + 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x28, 0x2b, 0xf4, 0x33, 0xb7, + 0x9c, 0x3a, 0xcc, 0x62, 0x29, 0xd6, 0x67, 0xf5, 0x2a, 0xff, 0x40, 0xff, + 0x0a, 0xee, 0xb3, 0xae, 0xe4, 0x1d, 0x52, 0x3c, 0x9d, 0xa3, 0x4b, 0xe6, + 0xbb, 0xb4, 0xd1, 0x71, 0x5f, 0xc0, 0x7d, 0xc3, 0x9c, 0x3a, 0xb8, 0x7b, + 0x5a, 0x2d, 0xbd, 0xc8, 0x59, 0xd7, 0xcf, 0xb4, 0x93, 0x9d, 0x7e, 0xe8, + 0x14, 0xc1, 0x3a, 0xf6, 0xd2, 0x34, 0xea, 0x09, 0xe2, 0xed, 0x13, 0xdf, + 0xe5, 0xbc, 0xb4, 0x81, 0xc3, 0xaf, 0xf4, 0x2d, 0xf6, 0x47, 0x36, 0x8e, + 0xbf, 0xb3, 0x8f, 0xe0, 0x41, 0xd7, 0xff, 0xce, 0x30, 0x9b, 0x5a, 0x4d, + 0x67, 0x73, 0x6c, 0xea, 0x09, 0xfe, 0x6c, 0x2b, 0xbf, 0xf9, 0x04, 0x12, + 0xcd, 0x69, 0x03, 0x87, 0x54, 0xc7, 0xcb, 0xe2, 0x4b, 0x31, 0x0a, 0xad, + 0x71, 0xff, 0x84, 0x5d, 0x1b, 0x76, 0x9f, 0xc9, 0x7c, 0x63, 0xf6, 0x31, + 0x7b, 0xf2, 0xa9, 0x5a, 0x7e, 0xa4, 0x1d, 0x7f, 0xe4, 0xdd, 0x56, 0xd7, + 0x3e, 0x7c, 0xee, 0xd9, 0xd7, 0xdd, 0x8f, 0x34, 0xea, 0x56, 0xa7, 0xda, + 0x14, 0xcb, 0xff, 0xca, 0xb2, 0x8c, 0xab, 0xce, 0x15, 0x57, 0xcf, 0x9d, + 0xdb, 0x3a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x74, 0xdf, 0xa0, 0x5c, 0x30, + 0x75, 0xe8, 0xf6, 0xd1, 0xd7, 0xd8, 0x1c, 0x09, 0xd7, 0xfc, 0xfb, 0x23, + 0xda, 0x03, 0x55, 0x27, 0x59, 0x85, 0x59, 0x3f, 0xd8, 0x85, 0x04, 0x8a, + 0x31, 0x89, 0x0c, 0xfa, 0x48, 0xe3, 0xc2, 0x41, 0x7f, 0xfd, 0x83, 0xe4, + 0x5f, 0x61, 0x05, 0xf8, 0xa1, 0xd7, 0xf4, 0xf1, 0xe7, 0x50, 0x07, 0x51, + 0xd7, 0xff, 0x47, 0x3f, 0xf9, 0xae, 0xc2, 0xdc, 0x4e, 0xbf, 0xd1, 0xcf, + 0xbd, 0xee, 0x7e, 0x75, 0x48, 0xfe, 0xba, 0x8b, 0x7f, 0x49, 0xe4, 0xe2, + 0xd3, 0xaf, 0xff, 0x67, 0xa1, 0x9f, 0xb3, 0xeb, 0x17, 0x0a, 0xe7, 0x59, + 0x85, 0x65, 0x32, 0x0c, 0x84, 0x24, 0xc4, 0x42, 0x57, 0x5c, 0x4e, 0x71, + 0x71, 0xa7, 0x5f, 0x63, 0x2a, 0xca, 0xce, 0xbf, 0xe4, 0xe0, 0xc6, 0xeb, + 0x7f, 0x1d, 0x7f, 0xff, 0xc0, 0xe4, 0xb5, 0xd7, 0x4e, 0x73, 0x80, 0xdd, + 0x38, 0xfa, 0x3a, 0xff, 0xc2, 0xec, 0xfb, 0x3a, 0xf3, 0x39, 0xd7, 0xff, + 0xf7, 0x44, 0x0e, 0xaf, 0x92, 0xee, 0x29, 0x81, 0x98, 0x07, 0x5c, 0xdc, + 0x3a, 0xa0, 0xfc, 0xd4, 0x5e, 0xbc, 0xa6, 0xa4, 0x75, 0xff, 0xa5, 0x9c, + 0xe3, 0xca, 0x7c, 0x64, 0xeb, 0xff, 0xb0, 0x31, 0x28, 0xe4, 0x7d, 0x71, + 0x3a, 0xff, 0xdb, 0x32, 0x4b, 0x0a, 0x6c, 0x80, 0x9d, 0x4b, 0x44, 0x1b, + 0xa1, 0x5c, 0xec, 0x4e, 0xa8, 0xea, 0x66, 0x7e, 0x42, 0xc3, 0x44, 0x5e, + 0x1d, 0xfb, 0x0c, 0x2a, 0xea, 0xae, 0x41, 0x94, 0xe3, 0x7f, 0xef, 0x23, + 0x50, 0x2e, 0x2a, 0x41, 0xd7, 0xfd, 0x1b, 0xf5, 0xf5, 0xe8, 0x64, 0xea, + 0x83, 0xf5, 0xe1, 0xe5, 0xc0, 0xe9, 0xd7, 0xe1, 0xce, 0xbf, 0x8e, 0xbf, + 0xa4, 0xf9, 0xb2, 0x02, 0x75, 0x2a, 0x0f, 0x49, 0x57, 0x92, 0xdf, 0x20, + 0x25, 0x07, 0x5f, 0x9e, 0x69, 0x27, 0x8e, 0xbf, 0xf4, 0x07, 0x91, 0x24, + 0xdf, 0xd8, 0x75, 0x49, 0x10, 0x9f, 0x90, 0x78, 0x9e, 0xff, 0xff, 0xa0, + 0x3d, 0xcd, 0xfc, 0x2f, 0xdf, 0xdf, 0x5a, 0x7e, 0x34, 0xeb, 0xfd, 0x99, + 0x8a, 0x28, 0xf2, 0x3a, 0x94, 0x44, 0xc7, 0x99, 0xaf, 0xdb, 0x13, 0x98, + 0x13, 0xaf, 0xff, 0xb5, 0xd4, 0xd7, 0xbb, 0x81, 0x4d, 0x60, 0x9d, 0x7b, + 0xb0, 0x38, 0x7e, 0xa0, 0x28, 0xbf, 0xd0, 0xbc, 0x45, 0xc2, 0xb9, 0xd7, + 0xfa, 0x4b, 0xd2, 0x0e, 0xf2, 0x3a, 0x9a, 0x7c, 0xd3, 0x19, 0xde, 0x77, + 0x69, 0xa2, 0x4c, 0xbd, 0xb4, 0x9a, 0x3a, 0x9a, 0x78, 0xbb, 0x44, 0xf7, + 0xe6, 0xaa, 0xca, 0xa5, 0x65, 0x50, 0x75, 0xfe, 0xcd, 0xfd, 0xe7, 0x96, + 0x8e, 0xa8, 0x3e, 0xde, 0x1d, 0x5f, 0xe1, 0x7f, 0x69, 0xa0, 0x13, 0xaf, + 0xff, 0xee, 0x67, 0xe9, 0xfb, 0x38, 0x9b, 0x07, 0x3d, 0xd4, 0x3a, 0xb1, + 0x11, 0xa8, 0x63, 0x52, 0x54, 0xc1, 0x90, 0x97, 0xe3, 0x42, 0xe1, 0x25, + 0xd8, 0x57, 0x5f, 0xc1, 0xfd, 0x51, 0xaf, 0xf6, 0xce, 0xbd, 0xa4, 0x09, + 0xd7, 0xf0, 0xc6, 0xeb, 0x7f, 0x1d, 0x7f, 0xd0, 0xdf, 0x03, 0xbc, 0x86, + 0x4e, 0xbf, 0xcd, 0x4e, 0x6a, 0x68, 0x73, 0xaf, 0xfe, 0x06, 0xba, 0xf2, + 0xeb, 0xca, 0x04, 0xea, 0xdc, 0xfd, 0x38, 0x65, 0x77, 0x52, 0x64, 0xc5, + 0xf8, 0x36, 0xb2, 0xcf, 0x42, 0xb6, 0xfb, 0xc8, 0xb7, 0x3a, 0xff, 0x27, + 0x75, 0x1e, 0x80, 0x9d, 0x58, 0x7a, 0x3e, 0x20, 0xbf, 0xe8, 0xef, 0x92, + 0x75, 0xc3, 0x4e, 0xbf, 0xff, 0x3b, 0x79, 0x1d, 0x1c, 0xf6, 0x30, 0xcb, + 0x2c, 0x95, 0x52, 0x45, 0x86, 0x88, 0x7c, 0x71, 0x7f, 0x35, 0xa0, 0x68, + 0xc1, 0xd7, 0xff, 0xb3, 0x79, 0x0c, 0x4b, 0x91, 0xe7, 0xf1, 0xd7, 0xfe, + 0x7f, 0x47, 0x35, 0xd8, 0x1f, 0x1d, 0x7e, 0xc9, 0x23, 0xec, 0x3a, 0x84, + 0xf8, 0xf4, 0x79, 0x52, 0x46, 0x60, 0x21, 0x57, 0x7f, 0xf8, 0x62, 0x5c, + 0xe0, 0x37, 0x4e, 0x3e, 0x8e, 0xbf, 0xfe, 0xd6, 0x28, 0x39, 0xed, 0x64, + 0x85, 0xd9, 0x3a, 0xed, 0x89, 0xd4, 0x4b, 0xf9, 0x26, 0xfb, 0x6a, 0x3b, + 0xa3, 0xaa, 0x0f, 0x53, 0x0c, 0x2f, 0xef, 0x08, 0x27, 0xdd, 0x5c, 0xeb, + 0xff, 0xd1, 0x38, 0xe6, 0x4f, 0xe5, 0x20, 0x64, 0x75, 0xff, 0x9c, 0x67, + 0xeb, 0xad, 0x34, 0x87, 0x53, 0xa2, 0xdc, 0x4c, 0x99, 0x49, 0xbc, 0xcb, + 0x2c, 0x95, 0x7d, 0x3a, 0xd3, 0x45, 0x30, 0x5f, 0xdd, 0x01, 0x3a, 0xdc, + 0x73, 0xc7, 0x13, 0x2b, 0xff, 0xff, 0x80, 0xe2, 0xde, 0x66, 0xc8, 0x1f, + 0x2e, 0x30, 0x43, 0x9b, 0xf8, 0xeb, 0xfd, 0x28, 0xe4, 0xf1, 0xc9, 0xce, + 0xbf, 0xb5, 0xa4, 0xc1, 0xfc, 0xeb, 0xdc, 0xc5, 0x73, 0xaf, 0xfd, 0x0c, + 0xfd, 0x9f, 0x58, 0xb8, 0x57, 0x3a, 0xb8, 0x88, 0xe5, 0x96, 0x78, 0x7a, + 0xa1, 0x1e, 0x59, 0x0c, 0x2b, 0xf2, 0x7a, 0x7c, 0x64, 0xeb, 0xfe, 0x86, + 0xf4, 0x41, 0xe8, 0xd1, 0xd7, 0xff, 0x26, 0xd4, 0x36, 0x17, 0x81, 0x75, + 0x9d, 0x7f, 0xfe, 0xf7, 0x72, 0x5f, 0x1b, 0xd4, 0xf6, 0xed, 0x4e, 0x1d, + 0x5c, 0x47, 0xda, 0xca, 0x3a, 0x6e, 0x28, 0x97, 0xfc, 0xb8, 0xe6, 0xcc, + 0xe4, 0x4c, 0x75, 0xff, 0xb8, 0xd5, 0xc6, 0xfa, 0xcd, 0x98, 0x75, 0xfe, + 0x1f, 0xf6, 0xf0, 0x38, 0xb3, 0xaf, 0xe1, 0xf9, 0xb7, 0x9c, 0x83, 0xaa, + 0x11, 0x4b, 0x88, 0x0e, 0x6b, 0x7f, 0xd8, 0xff, 0xfc, 0xc0, 0xbc, 0x8e, + 0xbf, 0xfc, 0xf3, 0xf5, 0x20, 0x72, 0x64, 0xe2, 0x1d, 0x58, 0x9e, 0x47, + 0xe7, 0x9a, 0x86, 0xff, 0x8b, 0x59, 0x39, 0xbf, 0x0e, 0x75, 0xfc, 0x75, + 0xff, 0xa5, 0x03, 0x3f, 0xde, 0x08, 0x24, 0x75, 0x2b, 0x9f, 0x2c, 0xc4, + 0xb7, 0xde, 0x9f, 0x02, 0x75, 0xff, 0x22, 0x9f, 0x79, 0xfa, 0xd3, 0x47, + 0x54, 0xc7, 0xbd, 0xb6, 0x45, 0x79, 0x96, 0x59, 0x3a, 0xff, 0xfd, 0x8b, + 0xf0, 0xc7, 0xf8, 0x1d, 0x62, 0xe1, 0xa5, 0x30, 0x5f, 0xdf, 0xec, 0x6f, + 0x52, 0x05, 0xa7, 0x5f, 0xee, 0x47, 0x91, 0xa8, 0x13, 0xaf, 0xd2, 0x9b, + 0x31, 0xa7, 0x5b, 0x87, 0x52, 0xb0, 0x7d, 0x10, 0x63, 0xf4, 0x9e, 0xb1, + 0x3f, 0x94, 0x84, 0x27, 0x51, 0x45, 0x8f, 0x50, 0x98, 0xbd, 0xe9, 0x74, + 0xeb, 0x21, 0xd7, 0xf7, 0x63, 0xe3, 0x52, 0x73, 0xaf, 0xee, 0x3f, 0x06, + 0x24, 0x75, 0xff, 0xf4, 0x29, 0xae, 0xba, 0x7a, 0x16, 0x2e, 0xa1, 0xd7, + 0xfe, 0xcd, 0x9d, 0x4f, 0x9a, 0xd2, 0x2c, 0xeb, 0x9f, 0xd2, 0x44, 0x7f, + 0x53, 0xaf, 0xfc, 0x92, 0x4e, 0x6f, 0x03, 0x1a, 0x3a, 0x95, 0xa2, 0x6c, + 0x41, 0x0f, 0xe1, 0x78, 0xc2, 0xeb, 0xc5, 0xd7, 0x49, 0x85, 0x6d, 0xb4, + 0xbe, 0x55, 0x34, 0x44, 0x2c, 0x25, 0x0c, 0x9c, 0x95, 0xf2, 0xa2, 0xd3, + 0x63, 0x4e, 0xde, 0x35, 0x04, 0x30, 0x9a, 0x1f, 0x1c, 0x8c, 0x4f, 0xb0, + 0xd7, 0x78, 0x4a, 0xfe, 0x4c, 0x31, 0xb1, 0x6a, 0x57, 0x4f, 0xa5, 0x57, + 0xed, 0xa9, 0x7d, 0x8d, 0xfa, 0xff, 0xf7, 0x31, 0x90, 0xf7, 0x26, 0x1c, + 0xe4, 0x8e, 0xbd, 0xcc, 0x57, 0x3a, 0xff, 0xd0, 0xcf, 0xd9, 0xf5, 0x8b, + 0x85, 0x73, 0xab, 0x88, 0xac, 0x5a, 0x57, 0x87, 0xaf, 0xff, 0x9d, 0x71, + 0xc6, 0xf0, 0x0a, 0x70, 0x0f, 0xa3, 0xab, 0x11, 0x00, 0x03, 0x0b, 0xfd, + 0xc6, 0x81, 0xc2, 0xb8, 0x3a, 0xff, 0xe8, 0xe7, 0xdf, 0x27, 0xbb, 0x81, + 0x43, 0xaf, 0xfd, 0xd1, 0x89, 0xfe, 0xf7, 0xae, 0xae, 0x75, 0x42, 0x2e, + 0x67, 0x32, 0xc4, 0x4b, 0xcf, 0xc9, 0xce, 0xb9, 0x96, 0x4e, 0xbc, 0xed, + 0x61, 0xa6, 0xd1, 0x91, 0xcb, 0xfa, 0x38, 0xf2, 0x4e, 0x9d, 0x7e, 0xc5, + 0xf5, 0xc2, 0x75, 0x98, 0x86, 0xfb, 0xdb, 0x23, 0xe8, 0x50, 0xa9, 0xb2, + 0xc2, 0xf9, 0x0a, 0x07, 0xad, 0x37, 0xc6, 0x54, 0xbe, 0xa1, 0xb7, 0xb1, + 0x8d, 0x93, 0x4d, 0xa2, 0xba, 0x93, 0xaf, 0xf3, 0x0c, 0xf1, 0x06, 0xf1, + 0x94, 0xf0, 0xa1, 0x70, 0x8b, 0xec, 0x65, 0x7f, 0xc3, 0x5b, 0x52, 0xcd, + 0xbd, 0x29, 0xf4, 0x15, 0xfb, 0xa5, 0xfd, 0xa8, 0x9a, 0x49, 0x31, 0xd7, + 0xff, 0xa2, 0x7c, 0xf4, 0x0a, 0x7f, 0x9b, 0xf8, 0xeb, 0x31, 0xa3, 0xf7, + 0xfa, 0x5d, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x8d, 0x6f, 0x29, 0xbe, 0x8e, + 0xb3, 0x18, 0x7a, 0x3e, 0x33, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x54, 0xb7, + 0x3b, 0x4d, 0x10, 0xd5, 0x98, 0xc3, 0xd5, 0x73, 0x3b, 0xf7, 0x1a, 0xee, + 0xd3, 0x44, 0x7d, 0x7f, 0xfc, 0x2f, 0xe9, 0x42, 0x9f, 0x23, 0xda, 0x8f, + 0xce, 0xbc, 0xf2, 0x63, 0x11, 0x09, 0xf4, 0xce, 0xff, 0xcf, 0x3c, 0x75, + 0x38, 0x90, 0xb3, 0xaf, 0xf4, 0x73, 0x07, 0xd9, 0xd3, 0xaf, 0x2f, 0x18, + 0xdb, 0x3e, 0xcf, 0xa7, 0x94, 0xc2, 0x36, 0xe2, 0x14, 0x57, 0xff, 0xfd, + 0x20, 0x71, 0x47, 0xd6, 0x06, 0x37, 0xd7, 0xdf, 0x28, 0x8a, 0x1d, 0x7f, + 0x03, 0x7d, 0xe5, 0x9e, 0x3a, 0xff, 0xf2, 0xac, 0xa3, 0x2a, 0xf3, 0x85, + 0x55, 0xf3, 0xe7, 0x76, 0xce, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x58, 0xf7, + 0x3e, 0x8e, 0xbf, 0xa7, 0xfb, 0xce, 0x67, 0x0e, 0xa9, 0x1e, 0x2b, 0x8a, + 0xdf, 0xf0, 0xba, 0x9d, 0x48, 0x19, 0xce, 0xbf, 0xff, 0x7f, 0x29, 0xd5, + 0x68, 0x56, 0xe7, 0x6f, 0x3e, 0x7c, 0xee, 0xd9, 0xd7, 0xe4, 0xf7, 0x93, + 0xc7, 0x5f, 0x73, 0x99, 0xb6, 0x75, 0x61, 0xe5, 0x39, 0x35, 0xfb, 0x39, + 0x99, 0x31, 0xd6, 0x62, 0x15, 0x64, 0x4e, 0xd9, 0x22, 0xfc, 0x62, 0x47, + 0x89, 0x88, 0x7a, 0x6f, 0xa8, 0x5a, 0xfd, 0x20, 0xbc, 0xab, 0x2d, 0x43, + 0xaf, 0xe5, 0x40, 0xe7, 0x5f, 0xc7, 0x5f, 0xe7, 0xff, 0x4f, 0xef, 0x39, + 0xd7, 0x2d, 0xa7, 0x50, 0x9e, 0x47, 0x8c, 0xaf, 0xfd, 0x8c, 0xf3, 0x05, + 0xf7, 0x96, 0x8e, 0xbf, 0x66, 0xba, 0x8c, 0x9d, 0x7d, 0xfa, 0xd3, 0x87, + 0x5f, 0xff, 0xf4, 0x70, 0x70, 0x39, 0xde, 0xa3, 0x7a, 0x9e, 0xd3, 0xee, + 0x75, 0x22, 0x21, 0xba, 0x45, 0x7f, 0x47, 0x3f, 0xdb, 0x07, 0x8e, 0xbf, + 0xe8, 0x1f, 0x2a, 0x9f, 0xc0, 0x83, 0xaf, 0xff, 0x47, 0x61, 0x6d, 0xea, + 0x7b, 0x31, 0x67, 0x5f, 0x7f, 0xfa, 0x7d, 0x3a, 0xf3, 0xbb, 0x4d, 0x16, + 0x85, 0xff, 0x9d, 0x9d, 0xa6, 0xbf, 0x27, 0xc6, 0x4e, 0xbf, 0xbf, 0x81, + 0x8f, 0x68, 0xea, 0x6a, 0x25, 0xb8, 0x4f, 0xfa, 0x1d, 0xff, 0xff, 0xf2, + 0x73, 0xae, 0x29, 0x1e, 0x4e, 0xc6, 0xbb, 0x9a, 0xe6, 0x37, 0x3c, 0x75, + 0x49, 0x50, 0xb0, 0x4c, 0x5a, 0x74, 0x88, 0xfc, 0x85, 0xdf, 0x4c, 0x6e, + 0xc5, 0x9d, 0x7f, 0xf3, 0xef, 0xb3, 0xaa, 0xe9, 0xe1, 0x85, 0x9d, 0x5c, + 0x3d, 0xd7, 0x15, 0xbf, 0xff, 0x27, 0xb4, 0xfb, 0xeb, 0x59, 0xd4, 0xd0, + 0x27, 0x3a, 0xff, 0xf8, 0x13, 0xf1, 0x3d, 0x38, 0x39, 0x2d, 0x2b, 0xa1, + 0xd5, 0xd4, 0x55, 0x8a, 0xb5, 0xff, 0xf0, 0x39, 0xc8, 0x1c, 0x51, 0x3b, + 0xdc, 0xfa, 0x75, 0x95, 0x27, 0x57, 0x0f, 0x90, 0x0a, 0x17, 0xf9, 0x60, + 0x1f, 0x68, 0x1c, 0x3a, 0xb8, 0x7a, 0xbb, 0x64, 0x57, 0xf6, 0xc9, 0xbb, + 0x9f, 0xb9, 0xd7, 0xe1, 0x6b, 0xe9, 0x0e, 0xbf, 0xff, 0xb8, 0x31, 0x1b, + 0xfc, 0xd7, 0x86, 0x03, 0xd8, 0xf1, 0xd7, 0x27, 0x4e, 0xbe, 0x90, 0xbf, + 0xd3, 0xaf, 0xf0, 0x5f, 0xfe, 0x71, 0xff, 0x3a, 0xfd, 0x9c, 0x6a, 0xbb, + 0x27, 0x52, 0x1e, 0xf8, 0x9a, 0x54, 0x26, 0x6d, 0x84, 0xaa, 0xeb, 0x6e, + 0x2a, 0x08, 0x40, 0xde, 0x75, 0x74, 0x3a, 0xff, 0xdf, 0x7c, 0xa2, 0x29, + 0x18, 0x30, 0x75, 0xfb, 0xef, 0x86, 0x3f, 0x3a, 0xb7, 0x44, 0x2f, 0x07, + 0x76, 0x1f, 0xdf, 0xa3, 0xd9, 0xd8, 0x3a, 0xff, 0xff, 0xf7, 0x50, 0x38, + 0x93, 0xf6, 0x23, 0xe6, 0x6f, 0x2d, 0x27, 0x9c, 0x70, 0xeb, 0xff, 0x66, + 0xf2, 0xd4, 0xdc, 0x7f, 0x68, 0xeb, 0xff, 0xec, 0xf6, 0xb2, 0x6e, 0xc6, + 0xcc, 0xef, 0x60, 0xeb, 0xfe, 0x18, 0x89, 0xb3, 0x62, 0x70, 0xea, 0x9d, + 0x36, 0x36, 0x92, 0xfe, 0xec, 0x28, 0x1e, 0x50, 0xbf, 0x7c, 0x9a, 0x49, + 0x31, 0xd5, 0x0a, 0x83, 0x72, 0x39, 0x64, 0x4c, 0xbf, 0xfb, 0xa9, 0xf3, + 0x07, 0x13, 0x8f, 0xb0, 0xeb, 0xff, 0xfd, 0xd8, 0x1c, 0xff, 0x58, 0x1e, + 0xc4, 0xeb, 0x00, 0x84, 0xea, 0x51, 0x14, 0x9e, 0x44, 0xbf, 0xff, 0xa2, + 0x6c, 0x0f, 0x63, 0x67, 0x73, 0xc3, 0x10, 0xb3, 0xaf, 0xed, 0xf5, 0xf6, + 0x70, 0x09, 0xd7, 0xfd, 0x0d, 0xea, 0x4c, 0xef, 0x39, 0xd4, 0xb4, 0x61, + 0xba, 0xd7, 0xe6, 0x37, 0xfa, 0x51, 0xc9, 0xe3, 0x93, 0x9d, 0x7f, 0xc8, + 0x01, 0x97, 0x23, 0x02, 0x75, 0xff, 0xff, 0x77, 0x24, 0xde, 0xa7, 0x63, + 0x39, 0x2f, 0x0c, 0x2f, 0x47, 0x56, 0x91, 0x35, 0xe3, 0x6a, 0x84, 0x78, + 0xe4, 0x33, 0xaf, 0xf7, 0x1b, 0x36, 0x27, 0x40, 0x75, 0xfe, 0x5c, 0x34, + 0x5f, 0x7f, 0x1d, 0x7f, 0x72, 0x3d, 0x3e, 0x32, 0x75, 0xff, 0xff, 0xf2, + 0x03, 0x9d, 0xc9, 0xa6, 0x7e, 0x4d, 0xee, 0x83, 0xfd, 0x62, 0x6c, 0x0c, + 0x1d, 0x7e, 0xf7, 0x5c, 0x54, 0x3a, 0xff, 0x84, 0x13, 0x87, 0xb8, 0x30, + 0x75, 0xb0, 0x28, 0xe0, 0xc8, 0x41, 0x34, 0x9e, 0xff, 0xf7, 0x3f, 0x6f, + 0xe3, 0x9e, 0xd3, 0xb8, 0x9d, 0x50, 0x9f, 0xae, 0x19, 0xa1, 0x90, 0xc6, + 0x1c, 0x03, 0x9b, 0xfd, 0x9d, 0x99, 0x3a, 0x8b, 0x3a, 0xff, 0x4b, 0x39, + 0xa1, 0x89, 0xce, 0xbd, 0xb7, 0x93, 0x9d, 0x7b, 0x3a, 0xe7, 0x5f, 0xa6, + 0x08, 0x00, 0x27, 0x50, 0x4f, 0x09, 0xc6, 0xaf, 0xf6, 0x33, 0x8d, 0x6e, + 0x32, 0x75, 0xff, 0x6e, 0xbc, 0xc1, 0xf6, 0xde, 0x1d, 0x79, 0x49, 0x00, + 0xeb, 0xf7, 0x63, 0x93, 0xac, 0xeb, 0xfc, 0x07, 0x1e, 0xe3, 0xcc, 0x75, + 0xb7, 0x98, 0xf6, 0x59, 0x28, 0xa4, 0x45, 0x0b, 0xbb, 0x56, 0x26, 0x5e, + 0xe6, 0x63, 0x0d, 0xba, 0xc5, 0x49, 0x1b, 0x99, 0x21, 0x93, 0xb0, 0xea, + 0x35, 0x0b, 0xbd, 0x07, 0x5c, 0xfe, 0x3a, 0xb8, 0x6a, 0xba, 0x2b, 0x7f, + 0xdc, 0xce, 0xe4, 0xff, 0x13, 0x47, 0x56, 0x1e, 0xd8, 0x08, 0x6f, 0xe4, + 0x10, 0x4b, 0x34, 0x75, 0xff, 0xb3, 0xd1, 0xbf, 0xef, 0xde, 0xa1, 0xd6, + 0x59, 0xd7, 0xf2, 0x08, 0x25, 0x9a, 0xf8, 0x79, 0xdb, 0x0f, 0xa9, 0x44, + 0x60, 0x79, 0xe6, 0xcc, 0x2b, 0x6d, 0xa0, 0xb2, 0xa8, 0x8a, 0x1d, 0xe7, + 0x21, 0x91, 0xf0, 0x61, 0x5b, 0x92, 0x8e, 0x14, 0x85, 0xd3, 0x61, 0x98, + 0x90, 0xdb, 0x98, 0x95, 0x71, 0xb3, 0x76, 0x57, 0x13, 0xc3, 0x67, 0xf8, + 0x73, 0x8c, 0x64, 0x3a, 0x94, 0x37, 0xe9, 0x52, 0xbb, 0x70, 0xd5, 0xfb, + 0x0e, 0x1b, 0xfb, 0x69, 0x02, 0x31, 0x31, 0xd7, 0xa1, 0xc4, 0xeb, 0xec, + 0xeb, 0xf8, 0xeb, 0x2a, 0x30, 0xfa, 0x3a, 0x5e, 0x23, 0x37, 0xff, 0xff, + 0xba, 0xe3, 0xed, 0x42, 0x4b, 0x36, 0x87, 0xd1, 0xd8, 0x50, 0x11, 0xb4, + 0x75, 0xf6, 0x6b, 0xf4, 0x3a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x6b, 0x5f, + 0xe5, 0xa2, 0xde, 0x6c, 0xe9, 0xd7, 0xf6, 0x6d, 0x69, 0xc5, 0xa7, 0x5e, + 0xe4, 0x2c, 0xeb, 0xfb, 0xb9, 0xa8, 0x9f, 0x68, 0xeb, 0xfe, 0x93, 0x19, + 0xc6, 0xbb, 0xb4, 0xd1, 0x41, 0xd6, 0x1f, 0xab, 0x98, 0x5f, 0x64, 0xd1, + 0xe3, 0xaf, 0xfa, 0x25, 0x1c, 0x9e, 0x39, 0x39, 0xd7, 0xff, 0xef, 0x69, + 0x27, 0x7d, 0x38, 0xbf, 0xbb, 0x13, 0x1d, 0x66, 0x15, 0x4a, 0xb0, 0xe0, + 0xde, 0x4f, 0x58, 0x42, 0x86, 0x73, 0x19, 0x70, 0xb9, 0x70, 0x90, 0xe9, + 0x00, 0x90, 0xfd, 0x39, 0xbf, 0xfc, 0xc2, 0xde, 0x4c, 0x67, 0x1a, 0xee, + 0xd3, 0x45, 0x17, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8b, 0xaa, 0xa1, + 0xbf, 0xf2, 0x93, 0xe3, 0x5f, 0x52, 0x38, 0x65, 0xca, 0xf0, 0xed, 0x69, + 0x47, 0xfc, 0xe5, 0x0e, 0xa1, 0x53, 0xe5, 0x7b, 0xf7, 0x1a, 0xee, 0xd3, + 0x44, 0x43, 0x7b, 0xb8, 0x13, 0xaf, 0xb3, 0x62, 0x70, 0xeb, 0x31, 0x87, + 0xe1, 0xb9, 0x9a, 0xb8, 0xdd, 0xb6, 0xce, 0xbe, 0x8e, 0xc2, 0xce, 0xbe, + 0x6b, 0xbb, 0x4d, 0x11, 0xb5, 0x34, 0xf3, 0x78, 0x41, 0x66, 0x02, 0x88, + 0x2c, 0x60, 0xbf, 0xcc, 0x67, 0x1a, 0xee, 0xd3, 0x45, 0x37, 0x7e, 0xe3, + 0x5d, 0xda, 0x68, 0xa8, 0x2f, 0x66, 0xec, 0x9d, 0x66, 0x30, 0xf4, 0x3a, + 0x67, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8a, 0x9a, 0xfd, 0xc6, 0xbb, + 0xb4, 0xd1, 0x58, 0x5f, 0x91, 0x90, 0x83, 0x87, 0x5c, 0xbd, 0x1d, 0x7f, + 0x26, 0xdb, 0xc2, 0x6d, 0x9d, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x88, + 0xfe, 0xa0, 0xfb, 0xe4, 0x61, 0x7b, 0x22, 0x73, 0xaf, 0xf6, 0x6f, 0x27, + 0x92, 0x09, 0xd7, 0x3f, 0x8e, 0xb3, 0x18, 0x9b, 0x13, 0x4c, 0xd6, 0x50, + 0xf0, 0x85, 0x12, 0x1f, 0x0d, 0xed, 0x98, 0xdf, 0xfe, 0x61, 0x6f, 0x26, + 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x6f, 0xbf, 0xf9, 0x6f, 0x26, 0x33, 0x8d, + 0x77, 0x69, 0xa2, 0x7e, 0xbf, 0x9f, 0xb9, 0xe8, 0x09, 0xd7, 0x0b, 0x4e, + 0xbe, 0xd4, 0xcb, 0xd1, 0xd7, 0xf9, 0xbd, 0x4f, 0x66, 0x2c, 0xeb, 0xb6, + 0x34, 0xf1, 0x81, 0x54, 0x22, 0x39, 0x05, 0x74, 0x47, 0xe3, 0x1b, 0xfc, + 0xab, 0x95, 0x81, 0xc9, 0xe3, 0x73, 0xaf, 0xca, 0xca, 0xa3, 0x6f, 0x37, + 0x3a, 0xfe, 0x56, 0x1e, 0x7e, 0xa2, 0xb9, 0xd7, 0xe5, 0x6d, 0x45, 0x31, + 0x5c, 0xeb, 0xb6, 0x34, 0xf1, 0x80, 0xdb, 0xa7, 0x52, 0xb2, 0x98, 0x6a, + 0xb0, 0x7c, 0xa8, 0x34, 0x55, 0xc6, 0xbe, 0x31, 0x01, 0x2d, 0xf2, 0xb7, + 0xc7, 0xc3, 0xaf, 0x95, 0x53, 0xaf, 0x47, 0x5f, 0xff, 0xca, 0xd8, 0xbf, + 0xa0, 0x5a, 0x8b, 0x08, 0x1f, 0x92, 0x3a, 0xff, 0x9f, 0xa9, 0xb1, 0x86, + 0x59, 0x64, 0xab, 0xfd, 0xd7, 0xf7, 0x9d, 0xd9, 0x3a, 0x95, 0x48, 0xf4, + 0x55, 0xe4, 0xea, 0xd5, 0x75, 0x57, 0x1f, 0x5f, 0xff, 0xe5, 0x65, 0x51, + 0xae, 0x42, 0x7b, 0xb8, 0x14, 0xd6, 0x0f, 0xe7, 0x5f, 0xca, 0xf1, 0xc7, + 0x79, 0x1d, 0x7e, 0xea, 0x3f, 0xea, 0xb8, 0xea, 0x56, 0x11, 0x86, 0xab, + 0x34, 0x78, 0xba, 0xce, 0x75, 0xf9, 0x54, 0xad, 0x3f, 0x52, 0x0e, 0xbf, + 0xfe, 0x88, 0x88, 0x88, 0x88, 0x88, 0xdf, 0x47, 0x5e, 0x4d, 0xf0, 0xeb, + 0xf7, 0x12, 0x77, 0x59, 0x57, 0x32, 0xc9, 0x55, 0x86, 0xfd, 0x92, 0x7b, + 0x00, 0xa6, 0x0d, 0x0d, 0x42, 0x39, 0x7f, 0x49, 0xd3, 0xdd, 0xf9, 0xdc, + 0x63, 0x68, 0xeb, 0xff, 0xc8, 0x38, 0xb8, 0xd6, 0xb2, 0x5b, 0x78, 0x75, + 0xff, 0xee, 0xc4, 0x9f, 0x02, 0x9b, 0x35, 0xfb, 0x4e, 0xbf, 0xdc, 0x00, + 0x83, 0xc0, 0xf1, 0xd7, 0xbb, 0x02, 0x75, 0xa1, 0x0f, 0x37, 0xc6, 0x75, + 0x08, 0xbe, 0xec, 0x26, 0x2f, 0x0a, 0x41, 0xd7, 0xe8, 0xfa, 0xbe, 0xa1, + 0xd5, 0xc3, 0xc1, 0x11, 0x9b, 0xfa, 0x5a, 0xf6, 0x0a, 0x87, 0x5e, 0x65, + 0xd9, 0x3a, 0xff, 0xf7, 0xb8, 0xf3, 0x87, 0xb1, 0xaf, 0x03, 0xa7, 0x5d, + 0x8b, 0xe9, 0xf4, 0x68, 0x76, 0xfc, 0xed, 0xea, 0x70, 0xeb, 0xff, 0xff, + 0xc2, 0xea, 0x27, 0x22, 0x5f, 0x3a, 0x8b, 0x0c, 0x7c, 0xdb, 0x07, 0x53, + 0x87, 0x5f, 0x3c, 0x93, 0x73, 0xaf, 0xfd, 0xd4, 0xf6, 0x73, 0x80, 0x9f, + 0x61, 0xd7, 0xfc, 0x9e, 0xce, 0x70, 0x13, 0xec, 0x3a, 0xf6, 0x80, 0x3f, + 0x0f, 0xf3, 0xa8, 0x34, 0x14, 0xe8, 0xb8, 0x5b, 0xd2, 0x61, 0x7d, 0xd4, + 0x27, 0x6d, 0x07, 0x5f, 0xff, 0x46, 0xf2, 0x71, 0xff, 0xe7, 0xe9, 0xc4, + 0x50, 0xea, 0xdb, 0x3e, 0x2d, 0xa0, 0xfb, 0xe9, 0xd6, 0x92, 0x3a, 0xfa, + 0x3f, 0xfa, 0xb3, 0xaf, 0x84, 0x0f, 0x23, 0xa9, 0xa7, 0x89, 0xa2, 0x4b, + 0xfd, 0xd8, 0x5b, 0x1f, 0xff, 0x07, 0x54, 0x22, 0xf7, 0x19, 0x90, 0x8a, + 0xfe, 0x99, 0x3b, 0xec, 0x69, 0xd5, 0xc3, 0xda, 0x72, 0xdb, 0xfe, 0xdc, + 0x3f, 0x61, 0x5f, 0xa0, 0xd1, 0xd7, 0xff, 0xe0, 0xf6, 0x38, 0x9f, 0xc7, + 0xd8, 0x98, 0x61, 0x67, 0x5f, 0xe5, 0x20, 0x7d, 0xa7, 0xe9, 0xd4, 0x88, + 0x88, 0x75, 0x6a, 0x84, 0x74, 0x0c, 0x31, 0xef, 0xf7, 0x62, 0x7e, 0x46, + 0x04, 0xeb, 0xff, 0xe1, 0xcd, 0x8d, 0x7e, 0x4e, 0xfe, 0x7d, 0xff, 0x3a, + 0xa1, 0x10, 0x8e, 0x65, 0x7f, 0x85, 0xe7, 0xde, 0x51, 0xb4, 0x75, 0xfe, + 0xd7, 0x5f, 0xef, 0x62, 0x47, 0x54, 0xe7, 0xd5, 0xb9, 0xb5, 0xec, 0xc9, + 0x8e, 0xbf, 0xe8, 0x90, 0xbf, 0xa4, 0x9b, 0x0e, 0xbd, 0xf6, 0x3f, 0x3a, + 0xba, 0x7a, 0xda, 0x38, 0xb2, 0xb9, 0xd7, 0xbd, 0x2c, 0x3a, 0xed, 0x61, + 0xd7, 0xff, 0x6a, 0x38, 0xdf, 0x0e, 0x4e, 0xe2, 0x75, 0x62, 0x29, 0xd0, + 0x89, 0xc4, 0xff, 0x1b, 0xf0, 0xad, 0xfc, 0x09, 0x81, 0xe8, 0xe9, 0xd7, + 0xff, 0x06, 0x3c, 0xfa, 0xce, 0xf5, 0x16, 0x75, 0xfe, 0x9c, 0x30, 0xfc, + 0xfc, 0x07, 0x5e, 0xf2, 0x4c, 0x75, 0x42, 0x24, 0xb1, 0x0b, 0x46, 0x97, + 0xe8, 0x57, 0x46, 0x5a, 0x75, 0x43, 0x2b, 0xa2, 0x73, 0x09, 0x13, 0x86, + 0x30, 0x7c, 0x68, 0xdc, 0x85, 0x25, 0x1b, 0xcd, 0x0b, 0x1e, 0x46, 0x7e, + 0xb8, 0xc2, 0x7b, 0x0a, 0xa7, 0x84, 0x5f, 0xe4, 0x83, 0x18, 0xc6, 0x92, + 0x3d, 0x0c, 0x0f, 0xa5, 0xd7, 0xff, 0xfc, 0xab, 0xd5, 0x51, 0x8a, 0xd7, + 0x8a, 0xa5, 0x5b, 0x62, 0xba, 0xae, 0x07, 0xcf, 0x9d, 0xdb, 0x3a, 0xf4, + 0xdf, 0x56, 0x75, 0xff, 0x67, 0xb5, 0x9e, 0xee, 0x7e, 0x75, 0x39, 0xeb, + 0x88, 0xfd, 0xce, 0x27, 0x57, 0x0d, 0xa2, 0xc8, 0x2f, 0xa3, 0xd8, 0xb3, + 0xaf, 0xde, 0x81, 0x4f, 0xce, 0xbf, 0xb1, 0x97, 0xfd, 0x78, 0x75, 0x7c, + 0x3f, 0x3c, 0x20, 0x12, 0x6b, 0xf7, 0x27, 0x8f, 0x68, 0xeb, 0xe7, 0xe3, + 0xc8, 0xeb, 0x73, 0x0f, 0x20, 0x4a, 0x2f, 0x32, 0xcb, 0x27, 0x5f, 0x4e, + 0x29, 0x05, 0x30, 0x5f, 0xdf, 0xf2, 0xbf, 0x5c, 0x64, 0x18, 0x9c, 0xeb, + 0xb7, 0x91, 0xd7, 0xf9, 0x48, 0xf6, 0xba, 0xe0, 0x3a, 0xfc, 0x93, 0xe6, + 0xfe, 0x3a, 0xe4, 0x69, 0xd5, 0x08, 0x87, 0x50, 0x5d, 0x66, 0x7e, 0x28, + 0xbf, 0x28, 0xfa, 0xd9, 0x23, 0xab, 0x73, 0xe7, 0xf1, 0xed, 0x2a, 0xca, + 0xfa, 0xa2, 0x31, 0xe0, 0xc2, 0x51, 0x1d, 0xfa, 0x8a, 0xe6, 0x00, 0x8c, + 0xa6, 0xff, 0xed, 0x8c, 0xe6, 0x85, 0x23, 0x99, 0x39, 0xd7, 0xff, 0xff, + 0xfe, 0x57, 0xf9, 0xdc, 0xde, 0x5d, 0x5f, 0xc6, 0xf4, 0x1e, 0xf6, 0x0f, + 0x73, 0xd0, 0x1f, 0x9f, 0x3b, 0xb6, 0x75, 0xff, 0x07, 0x00, 0xa9, 0x4e, + 0xba, 0xce, 0xbf, 0x42, 0xc7, 0x26, 0x3b, 0x0d, 0xdd, 0xed, 0x98, 0x13, + 0xaf, 0xf2, 0x9d, 0x48, 0x10, 0x41, 0xd5, 0xd3, 0xce, 0x71, 0xda, 0x0a, + 0x29, 0x35, 0x08, 0x3b, 0xfa, 0x25, 0xd8, 0xd8, 0x87, 0x5f, 0x9f, 0x80, + 0x7d, 0x1d, 0x74, 0xbc, 0x75, 0xf4, 0xd1, 0xe7, 0x3a, 0xf8, 0x1f, 0xe0, + 0xb4, 0xdb, 0x80, 0x5a, 0xd2, 0x3a, 0xa7, 0x3c, 0x8e, 0x9c, 0x5f, 0xfd, + 0x1d, 0xfa, 0x1f, 0x26, 0x4d, 0x0b, 0x3a, 0xfa, 0x3c, 0x05, 0x9d, 0x46, + 0x88, 0x3a, 0xfe, 0x79, 0xff, 0x71, 0x09, 0x2b, 0x06, 0xdb, 0x4d, 0x3d, + 0x2d, 0xb1, 0x7a, 0x5a, 0x27, 0xbc, 0xe7, 0x7f, 0xfe, 0x5e, 0x9e, 0x5d, + 0x4c, 0xf6, 0xb9, 0x81, 0xc3, 0xaf, 0xfa, 0x3c, 0x39, 0xb0, 0x73, 0x47, + 0x54, 0x22, 0xb7, 0x08, 0xf4, 0xa7, 0x7f, 0x3f, 0x61, 0x5c, 0x12, 0x3a, + 0xa4, 0xab, 0x89, 0xa5, 0xbc, 0x85, 0x2a, 0xc8, 0xfd, 0x1c, 0x86, 0xc2, + 0xeb, 0xfa, 0x43, 0x9b, 0xfb, 0x0e, 0xbf, 0xff, 0x7d, 0xff, 0xf8, 0xdf, + 0x27, 0x0b, 0xbb, 0x5c, 0x27, 0x54, 0x22, 0x17, 0x85, 0x97, 0xf9, 0xc7, + 0xd2, 0xce, 0x61, 0xd7, 0xf0, 0xa7, 0xfa, 0xea, 0x1d, 0x77, 0x02, 0x75, + 0xcc, 0xb2, 0x75, 0x48, 0xd7, 0x32, 0x2d, 0x7a, 0x13, 0x61, 0x4c, 0x1a, + 0x2a, 0x74, 0x54, 0xe9, 0xf2, 0xef, 0xf4, 0x75, 0xfc, 0x9d, 0x45, 0x14, + 0x83, 0xae, 0xd7, 0xd0, 0x9e, 0x27, 0x85, 0xe9, 0x11, 0x2d, 0xf5, 0x9a, + 0xf3, 0x2c, 0xb2, 0x55, 0x14, 0xc1, 0x7f, 0x7c, 0x8c, 0xa4, 0xc5, 0x53, + 0x4d, 0xe2, 0x0d, 0x5f, 0xb3, 0x91, 0xb3, 0x0e, 0xa8, 0x64, 0x0d, 0x4e, + 0x8b, 0x91, 0xc4, 0xa4, 0xb0, 0xae, 0x43, 0xad, 0x64, 0x5d, 0x8d, 0xbc, + 0x5f, 0xf4, 0x41, 0x7d, 0xc9, 0x03, 0x0e, 0xbf, 0xc3, 0xbf, 0xbe, 0xf5, + 0xff, 0x3a, 0xf0, 0xa6, 0x8e, 0xbe, 0x0b, 0x8f, 0xe7, 0x5f, 0xfd, 0x03, + 0xf8, 0xc6, 0xf3, 0x40, 0xfe, 0x75, 0x62, 0x2d, 0x50, 0xdb, 0xf1, 0xad, + 0x10, 0xd9, 0x0e, 0xbf, 0xe7, 0x51, 0xbd, 0x40, 0xbc, 0x8e, 0xbe, 0x9e, + 0x77, 0xdc, 0xeb, 0xbf, 0xd2, 0x1f, 0x58, 0x87, 0xfd, 0x38, 0xbf, 0x46, + 0x73, 0xa8, 0x75, 0xff, 0xe6, 0x7f, 0xee, 0x64, 0xe9, 0x9b, 0x23, 0x73, + 0xaf, 0xff, 0x7f, 0x0b, 0xe7, 0x22, 0x7f, 0x3b, 0xa8, 0x75, 0xfe, 0x96, + 0x77, 0x17, 0x0d, 0x3a, 0xf6, 0x2d, 0x5c, 0xeb, 0xfd, 0x9a, 0x1c, 0xf7, + 0x50, 0xea, 0x09, 0xe7, 0x08, 0xf5, 0x62, 0x73, 0x33, 0x1e, 0x74, 0x97, + 0xf4, 0xdf, 0x25, 0xec, 0x7f, 0xbf, 0xbd, 0x93, 0x0c, 0x2c, 0xf1, 0x01, + 0x5f, 0x9c, 0x43, 0xd8, 0x34, 0x40, 0x4c, 0x1b, 0x9b, 0xff, 0x93, 0x7d, + 0x07, 0x06, 0x04, 0x10, 0x75, 0xff, 0xc0, 0x6a, 0x9c, 0xcd, 0xf5, 0xfb, + 0xf8, 0xeb, 0xf4, 0x49, 0xf7, 0x64, 0xea, 0xc4, 0x58, 0x22, 0x0f, 0x11, + 0xed, 0x39, 0xd7, 0xef, 0x99, 0x32, 0x2c, 0xeb, 0xff, 0xc0, 0x8f, 0x9b, + 0x5e, 0x4d, 0x77, 0x77, 0x64, 0xea, 0x9c, 0xfe, 0x74, 0x53, 0x7f, 0xec, + 0x0f, 0x5d, 0x88, 0xec, 0x6e, 0x75, 0x2a, 0x11, 0xd7, 0xc8, 0x45, 0x2c, + 0x8e, 0xff, 0xc8, 0x2a, 0x70, 0x51, 0xa0, 0x13, 0xaf, 0xff, 0xcf, 0xbe, + 0xfa, 0x81, 0xf7, 0xd9, 0xba, 0x9e, 0xd1, 0xd5, 0x08, 0xce, 0xc3, 0x90, + 0x1e, 0x5f, 0x2e, 0x31, 0x67, 0x5f, 0xfb, 0x17, 0x0d, 0x4f, 0x70, 0x0b, + 0x3a, 0xf2, 0x6f, 0xa3, 0xad, 0x12, 0x3d, 0x9f, 0xcf, 0x6f, 0xf7, 0x26, + 0xd2, 0x0f, 0x90, 0xeb, 0xfd, 0xd4, 0xdf, 0xfe, 0x38, 0x4e, 0xbe, 0xdf, + 0xfe, 0x41, 0x57, 0x32, 0xc9, 0x55, 0x06, 0xed, 0x92, 0x3b, 0x85, 0x0a, + 0x60, 0xd0, 0xde, 0x7e, 0x4b, 0xe2, 0x2d, 0x65, 0x09, 0x0a, 0x56, 0xd9, + 0x0e, 0xb1, 0x0d, 0x6c, 0x94, 0x80, 0x90, 0x94, 0xe4, 0x3c, 0xfb, 0x1f, + 0x3b, 0x97, 0x0b, 0xcf, 0x8a, 0x01, 0x0e, 0x7b, 0xd3, 0xba, 0xce, 0xbd, + 0xe4, 0x64, 0xf1, 0x84, 0x5f, 0x78, 0x0f, 0xf4, 0xd1, 0x03, 0xee, 0x6a, + 0x69, 0xd1, 0x0c, 0x04, 0x5b, 0xca, 0xe9, 0xf9, 0xd7, 0x40, 0x0e, 0xbf, + 0x00, 0x7f, 0xfb, 0x23, 0xaf, 0xff, 0x87, 0x35, 0xf3, 0xef, 0x63, 0xf5, + 0xbc, 0xbe, 0x61, 0xbf, 0xd0, 0xad, 0x01, 0x19, 0x3b, 0x17, 0xaf, 0xfd, + 0xd0, 0x4f, 0x1f, 0x23, 0xd0, 0x13, 0xaf, 0x3f, 0x27, 0x3a, 0xe6, 0x59, + 0x3a, 0xff, 0x71, 0x33, 0x67, 0xd9, 0x30, 0xd3, 0x68, 0xc8, 0xe5, 0xff, + 0x91, 0x4f, 0x9a, 0x07, 0xeb, 0x89, 0x1d, 0x7f, 0xb5, 0x9e, 0x75, 0xe0, + 0x9d, 0x41, 0x4c, 0xd7, 0x8e, 0x9d, 0x4f, 0xf2, 0x15, 0xff, 0xc3, 0x8a, + 0x75, 0xe5, 0xf5, 0xf7, 0x83, 0xaa, 0x11, 0x07, 0x87, 0xd7, 0xff, 0x2d, + 0x6f, 0x2c, 0xe3, 0x5d, 0xda, 0x68, 0x86, 0x2f, 0xff, 0xff, 0x3e, 0xb0, + 0x71, 0xbd, 0x8d, 0xe5, 0xb7, 0x9d, 0x6a, 0x60, 0xba, 0x87, 0x56, 0x23, + 0x18, 0x09, 0xf4, 0x8a, 0xb9, 0xbb, 0x1e, 0xe8, 0xc3, 0x9e, 0xff, 0x2f, + 0xaf, 0x38, 0xc4, 0x8a, 0xbb, 0x40, 0x3a, 0xfe, 0x97, 0x5d, 0xc6, 0x0e, + 0xb4, 0x34, 0xf0, 0x37, 0x16, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x41, 0x57, + 0xbb, 0x0b, 0x3a, 0xff, 0xd1, 0x3b, 0xfb, 0x99, 0x2d, 0xbc, 0x3a, 0xb1, + 0x11, 0xc8, 0x66, 0x23, 0x77, 0xee, 0xc2, 0xc1, 0xb9, 0xd7, 0xde, 0xd4, + 0x7e, 0x55, 0xe7, 0xe4, 0xe5, 0x5f, 0x00, 0x5d, 0x42, 0xaf, 0xf2, 0x4f, + 0x9e, 0xd4, 0x7e, 0x55, 0x15, 0x7f, 0x63, 0x63, 0xb0, 0xb2, 0xae, 0x65, + 0x92, 0xaf, 0xe1, 0x81, 0x9d, 0x38, 0x55, 0x62, 0x61, 0x4d, 0x22, 0x58, + 0xe7, 0x48, 0x7f, 0x33, 0x10, 0xa6, 0x4a, 0xfe, 0x8c, 0x5c, 0x9c, 0x29, + 0x83, 0xf4, 0xa9, 0x27, 0xf5, 0x31, 0x6f, 0x63, 0xa6, 0xa8, 0x56, 0xb5, + 0xd7, 0x27, 0x95, 0x61, 0x7f, 0x60, 0xe9, 0x07, 0x0e, 0xbd, 0xd0, 0x2c, + 0xea, 0xe9, 0xe2, 0xed, 0x14, 0xdf, 0xe7, 0x1c, 0xd7, 0x23, 0x47, 0x5f, + 0xc1, 0xc1, 0x7f, 0x68, 0xeb, 0x44, 0x8f, 0x6f, 0x46, 0x17, 0xee, 0x6f, + 0x2c, 0xf1, 0xd7, 0xff, 0xfd, 0xd4, 0xe6, 0x05, 0xd7, 0x83, 0xe1, 0x86, + 0x73, 0xda, 0x3a, 0xd0, 0x75, 0xfb, 0xb1, 0xb0, 0x30, 0xd3, 0xf2, 0xfd, + 0x8e, 0xb8, 0x8d, 0xbf, 0x42, 0x6a, 0xff, 0x6f, 0x2d, 0xb8, 0x6e, 0x2c, + 0xeb, 0xff, 0xff, 0x73, 0x91, 0xbc, 0xb7, 0xd2, 0x71, 0xbd, 0xcf, 0xbc, + 0x48, 0x09, 0xd5, 0x08, 0xa5, 0xc3, 0x6b, 0xff, 0xf3, 0x54, 0x7d, 0x67, + 0x24, 0x9d, 0x71, 0xde, 0x47, 0x5f, 0xf9, 0xb1, 0xed, 0x67, 0x93, 0x76, + 0x4e, 0xb3, 0xe2, 0x25, 0x14, 0x55, 0xa8, 0x4e, 0xab, 0xb0, 0xcd, 0x18, + 0x5a, 0xde, 0xf3, 0xfe, 0x75, 0xff, 0xf9, 0xde, 0x4f, 0xdf, 0x99, 0x38, + 0x3c, 0x07, 0xfa, 0x68, 0xbe, 0xef, 0x7f, 0x01, 0x3a, 0xff, 0xda, 0x41, + 0xde, 0x5c, 0x04, 0x68, 0xea, 0x99, 0x17, 0xfc, 0x65, 0xf0, 0xe5, 0xfe, + 0x89, 0xfb, 0x93, 0x42, 0xb9, 0xd6, 0x69, 0xd7, 0xff, 0xfb, 0xf4, 0xe2, + 0x9d, 0x85, 0xcd, 0x24, 0x1e, 0xc7, 0x20, 0xeb, 0x7b, 0x0f, 0xc7, 0x42, + 0x17, 0xde, 0x1c, 0x91, 0xd5, 0x07, 0x8e, 0x84, 0xf7, 0xfe, 0x14, 0x97, + 0xbb, 0x9c, 0x4d, 0x1d, 0x7f, 0x44, 0x87, 0x32, 0x73, 0xaf, 0xf3, 0x86, + 0x3f, 0x86, 0x74, 0x75, 0x74, 0xf7, 0x9c, 0xae, 0xfe, 0xdb, 0x56, 0xbf, + 0x3e, 0x77, 0x6c, 0xf1, 0x00, 0xdf, 0xef, 0x7f, 0xf4, 0x65, 0xdc, 0x3c, + 0x40, 0x37, 0x9f, 0x92, 0x3c, 0x40, 0x35, 0x87, 0xd4, 0x04, 0x2b, 0x9e, + 0x47, 0x88, 0x06, 0xf9, 0xc7, 0x79, 0x1e, 0x20, 0x1b, 0xfc, 0x8d, 0xee, + 0x7f, 0xfc, 0x1e, 0x20, 0x1b, 0xc8, 0x21, 0x3c, 0x40, 0x34, 0x14, 0x5b, + 0xac, 0x8b, 0xa5, 0xdb, 0x10, 0x2c, 0xa1, 0xe2, 0x01, 0xbd, 0xc8, 0xf1, + 0xe2, 0x01, 0xa3, 0xc4, 0x03, 0x7b, 0x6d, 0x3f, 0x3c, 0x40, 0x37, 0x42, + 0xcf, 0x10, 0x0d, 0x04, 0xf9, 0x70, 0x5d, 0x0b, 0x2f, 0x91, 0x61, 0x83, + 0xc4, 0x03, 0x7b, 0xce, 0xd3, 0xc4, 0x03, 0x7f, 0xe1, 0x79, 0x31, 0xd4, + 0x6b, 0xf0, 0xf1, 0x00, 0xdf, 0xfc, 0xfe, 0x04, 0xe8, 0x3e, 0xeb, 0xc8, + 0xf1, 0x00, 0xdc, 0xe1, 0x3c, 0x40, 0x37, 0xf8, 0x5d, 0x9d, 0x6a, 0x3f, + 0x3c, 0x40, 0x37, 0xe4, 0x51, 0xc7, 0xf3, 0xc4, 0x03, 0x72, 0x68, 0xf1, + 0x00, 0xd7, 0x0f, 0x5b, 0xc6, 0x97, 0xff, 0xba, 0x9e, 0xf6, 0x6b, 0xe7, + 0x12, 0x16, 0x78, 0x80, 0x6f, 0xde, 0x18, 0xde, 0x46, 0x88, 0x06, 0xef, + 0xe0, 0xf1, 0x00, 0xb0, 0x6d, 0x2f, 0xc9, 0x0b, 0x70, 0x9e, 0x20, 0x1b, + 0xe0, 0x38, 0xb4, 0xf1, 0x00, 0xde, 0x8e, 0x34, 0xf1, 0x00, 0xdf, 0xfb, + 0x37, 0xd0, 0x63, 0x07, 0xfd, 0x1e, 0x20, 0x1b, 0xf0, 0x1e, 0x52, 0x83, + 0xc4, 0x03, 0x7e, 0x76, 0xf6, 0x37, 0x3c, 0x40, 0x35, 0x88, 0xb2, 0xea, + 0x58, 0x0c, 0xee, 0xe7, 0xe7, 0x88, 0x06, 0xa4, 0xac, 0x94, 0x24, 0x59, + 0x09, 0x66, 0x91, 0x24, 0x22, 0xfa, 0x69, 0xf9, 0x96, 0x8b, 0x7d, 0x0d, + 0xa0, 0x17, 0xdf, 0xb3, 0xda, 0x7d, 0xcf, 0x10, 0x0d, 0xfe, 0x0c, 0x36, + 0x6e, 0x47, 0x8f, 0x10, 0x08, 0x4d, 0xa5, 0xee, 0x43, 0x27, 0x88, 0x06, + 0x9a, 0x7f, 0x3c, 0x50, 0xbf, 0xc0, 0x79, 0x4a, 0x3e, 0xac, 0xf1, 0x00, + 0xdf, 0x20, 0xcb, 0x47, 0x88, 0x06, 0xfe, 0x79, 0xa5, 0x9b, 0xc8, 0xf1, + 0x00, 0xd6, 0x23, 0x2f, 0xa4, 0x5f, 0xa0, 0x80, 0xb6, 0xff, 0xbb, 0x1a, + 0x63, 0x40, 0xe7, 0xe7, 0x88, 0x06, 0xc8, 0x78, 0x80, 0x6e, 0x79, 0xc2, + 0x7c, 0x9d, 0x48, 0xbb, 0x9f, 0x9e, 0x20, 0x1b, 0xf3, 0xfb, 0x49, 0xb9, + 0xe2, 0x01, 0xbf, 0x90, 0x41, 0x2c, 0xd1, 0xe2, 0x01, 0xa8, 0x44, 0x80, + 0x92, 0x78, 0xd2, 0xa1, 0x94, 0xb0, 0x18, 0x5a, 0xe4, 0x36, 0x10, 0xfe, + 0x61, 0xee, 0x42, 0x37, 0xa5, 0xae, 0x5b, 0xf9, 0x40, 0xa5, 0x6a, 0x5b, + 0xaf, 0xa5, 0x09, 0xed, 0xc2, 0x87, 0xec, 0x2f, 0xaf, 0x79, 0x19, 0x3c, + 0x61, 0x37, 0x9d, 0xda, 0x68, 0x80, 0x58, 0x4c, 0x57, 0x78, 0x76, 0x5f, + 0x28, 0xad, 0x02, 0xb3, 0xae, 0xd9, 0x39, 0xd7, 0xed, 0x83, 0x01, 0xe9, + 0xd5, 0x07, 0x82, 0x83, 0x37, 0xff, 0x48, 0x71, 0xbd, 0x4f, 0xff, 0x04, + 0xc7, 0x5d, 0xfc, 0x15, 0x65, 0x0a, 0xbd, 0xd8, 0x9c, 0xeb, 0x99, 0x64, + 0xaa, 0x43, 0xdb, 0x57, 0x16, 0x98, 0x45, 0x91, 0xcb, 0xcb, 0x4d, 0x14, + 0xc1, 0xe0, 0x5e, 0x40, 0x78, 0xeb, 0xff, 0xde, 0xd6, 0x28, 0x9c, 0xfb, + 0xff, 0xf1, 0xb9, 0xd5, 0x3b, 0x3a, 0x62, 0x44, 0x01, 0x84, 0xd3, 0x69, + 0x71, 0xc8, 0x9d, 0xc6, 0xa7, 0x20, 0xfe, 0x1c, 0x3e, 0x2d, 0xfa, 0x37, + 0x7f, 0xf8, 0x7d, 0xb7, 0x93, 0x49, 0xf9, 0x38, 0x60, 0xeb, 0xfb, 0xdf, + 0x76, 0x6c, 0x8d, 0x1d, 0x7f, 0xb3, 0x7f, 0x79, 0xe5, 0xa3, 0xaf, 0x0e, + 0xf2, 0x3c, 0x60, 0x15, 0x88, 0xdc, 0x44, 0xde, 0x19, 0xb9, 0x9d, 0xfa, + 0x69, 0x47, 0x27, 0x3a, 0xfa, 0x14, 0x85, 0x9d, 0x5c, 0x3c, 0xa5, 0x94, + 0xdf, 0xfa, 0x5a, 0xf8, 0x38, 0xb8, 0xe2, 0x87, 0x5f, 0xd2, 0x8e, 0x7f, + 0xf5, 0x67, 0x5f, 0xfd, 0xb0, 0x73, 0x5e, 0xc1, 0x96, 0x68, 0xeb, 0xe5, + 0xc0, 0x3c, 0x75, 0x61, 0xf2, 0x3a, 0x1d, 0xdd, 0x7c, 0x45, 0xa0, 0xc2, + 0x52, 0xff, 0xa1, 0xb0, 0xb4, 0x5f, 0xe8, 0x75, 0x70, 0xfa, 0x36, 0x8c, + 0x6f, 0xef, 0xac, 0xf1, 0x33, 0xa5, 0x5f, 0xfd, 0xf8, 0xa6, 0x6f, 0xe9, + 0xa4, 0xfc, 0x3a, 0xfa, 0x6e, 0xbc, 0xc7, 0x5f, 0x35, 0xf9, 0x39, 0xd7, + 0xec, 0x9a, 0x51, 0xb9, 0xd7, 0xba, 0x93, 0x1d, 0x78, 0x62, 0x45, 0x5f, + 0xf8, 0x7f, 0x4d, 0xad, 0xa0, 0x4a, 0x15, 0xce, 0xac, 0x3e, 0x17, 0x1a, + 0xad, 0xd3, 0x4f, 0xe2, 0x2f, 0x48, 0xc4, 0x8b, 0xc5, 0x1b, 0x4f, 0xb5, + 0x0a, 0xdf, 0x30, 0x89, 0x23, 0x5c, 0xe9, 0x2b, 0xc6, 0xfd, 0x7f, 0x6f, + 0xae, 0x72, 0x3c, 0x75, 0xfd, 0x2d, 0x29, 0xc7, 0x69, 0xd7, 0x87, 0xda, + 0x3a, 0xfd, 0xa0, 0x08, 0x1a, 0x75, 0x41, 0xf8, 0x21, 0x70, 0x06, 0xef, + 0xfe, 0xeb, 0x31, 0xcd, 0x63, 0x2f, 0xc5, 0x0e, 0xbf, 0x60, 0x43, 0x8b, + 0x3a, 0xff, 0xf7, 0xb7, 0x6a, 0x77, 0x6e, 0x3d, 0xdf, 0xba, 0x3a, 0xe5, + 0x4e, 0x8e, 0xbe, 0x14, 0xde, 0x47, 0x5f, 0xf2, 0x6f, 0xdc, 0x0f, 0x1d, + 0xa7, 0x54, 0x1e, 0xcf, 0x08, 0x6f, 0xfb, 0xb1, 0xc8, 0x6a, 0x0b, 0x4e, + 0xbe, 0xf2, 0x8f, 0xae, 0x1e, 0xbe, 0xd1, 0x0d, 0x49, 0x3c, 0x3e, 0x23, + 0x2c, 0x98, 0x0a, 0x0c, 0xc3, 0x2a, 0xfd, 0xb4, 0x05, 0xe0, 0x4e, 0xbf, + 0xf7, 0x73, 0x69, 0xc5, 0x4c, 0xdf, 0xc7, 0x5f, 0xf6, 0x37, 0xa8, 0x1e, + 0x81, 0x43, 0xaf, 0x7b, 0x1a, 0x75, 0x2c, 0xf5, 0x34, 0x73, 0x7a, 0x4b, + 0xfc, 0xea, 0x51, 0x1a, 0x9f, 0xc2, 0x57, 0xc4, 0x57, 0xfc, 0xa3, 0xfc, + 0x85, 0x8a, 0x28, 0x75, 0xff, 0x9f, 0x4b, 0x84, 0xe7, 0x11, 0x93, 0xad, + 0xa5, 0x0f, 0xdf, 0xa7, 0x57, 0xfd, 0x9e, 0xf2, 0x29, 0xec, 0x69, 0xd7, + 0xf8, 0x31, 0xbe, 0xb3, 0x7f, 0x1d, 0x7f, 0xd1, 0xe4, 0x6a, 0x06, 0x3c, + 0x75, 0xb4, 0x14, 0x51, 0x61, 0xc7, 0x0d, 0x2b, 0x74, 0xc0, 0x3d, 0x0c, + 0xbb, 0xfe, 0xf2, 0x4f, 0x1b, 0xff, 0xc8, 0x3a, 0xf6, 0xbd, 0x87, 0x5d, + 0x9a, 0xf8, 0x7a, 0xbf, 0x4e, 0xaf, 0xfe, 0xcf, 0x26, 0xf2, 0x18, 0x55, + 0x2a, 0xfd, 0xb3, 0xaf, 0xd9, 0xef, 0xdf, 0xc7, 0x54, 0x8f, 0xdf, 0x6d, + 0x42, 0xff, 0xfd, 0x1d, 0x7c, 0x18, 0xe2, 0x81, 0x03, 0xf2, 0x47, 0x54, + 0x93, 0x20, 0xf4, 0x2a, 0x36, 0x89, 0x6a, 0x17, 0x35, 0x71, 0x45, 0x21, + 0xfc, 0xf1, 0xd7, 0x02, 0x39, 0xfb, 0xee, 0xa3, 0xc8, 0xeb, 0xfd, 0x83, + 0x2c, 0xd7, 0xd5, 0x9d, 0x7e, 0x5e, 0xbf, 0x77, 0x3a, 0xbc, 0x7b, 0x5f, + 0x4c, 0xef, 0xfb, 0x98, 0x3f, 0x3b, 0x9b, 0xb2, 0x75, 0xff, 0x48, 0x41, + 0xff, 0xc6, 0xaf, 0xf3, 0xaa, 0x74, 0xc5, 0xa4, 0xf5, 0x84, 0x9b, 0x9d, + 0xdf, 0xf0, 0xc6, 0x6f, 0xec, 0xe4, 0x1d, 0x50, 0x7e, 0xae, 0x7f, 0x7e, + 0x7d, 0x81, 0x0c, 0x1d, 0x76, 0xb4, 0x75, 0xe6, 0x59, 0x64, 0xeb, 0xbf, + 0x72, 0x98, 0x2f, 0xeb, 0x87, 0xb7, 0xa3, 0x5b, 0xff, 0x66, 0x85, 0xd4, + 0x98, 0x52, 0x63, 0xaf, 0xef, 0xe2, 0x5d, 0xfb, 0xa3, 0xaf, 0x3f, 0xf8, + 0x55, 0x49, 0x32, 0xe5, 0xc2, 0x0f, 0xa4, 0x5f, 0x9f, 0x6d, 0x98, 0x5f, + 0x40, 0x50, 0x27, 0x5f, 0x83, 0xc4, 0x04, 0xe7, 0x5f, 0xe6, 0x70, 0x73, + 0x62, 0x70, 0xeb, 0xf8, 0x73, 0x7f, 0xfe, 0xc8, 0xea, 0x99, 0x11, 0x62, + 0x51, 0xe3, 0x3b, 0x9d, 0x67, 0x5f, 0xec, 0xd9, 0x8c, 0x32, 0xcb, 0x25, + 0x5f, 0xa6, 0x8c, 0xee, 0x8e, 0xa1, 0x3d, 0xff, 0xa7, 0x17, 0xf9, 0x53, + 0x00, 0x6f, 0x53, 0x87, 0x5e, 0x5b, 0xf8, 0xea, 0x99, 0x1d, 0x1d, 0x74, + 0x01, 0x1e, 0xc3, 0x6b, 0xf8, 0x76, 0x3a, 0xd1, 0x67, 0x5f, 0xb2, 0x69, + 0x44, 0x8e, 0xbf, 0xa7, 0x0c, 0x60, 0x84, 0xea, 0x85, 0x5a, 0xf2, 0x54, + 0x48, 0x55, 0xbc, 0x63, 0x1a, 0x40, 0xf1, 0x6f, 0xd2, 0x7b, 0xcf, 0xfa, + 0x1d, 0x7f, 0xc1, 0x10, 0x6b, 0x27, 0xc9, 0xce, 0xbd, 0x1c, 0x13, 0xaf, + 0xf6, 0x04, 0x5f, 0x48, 0x13, 0xad, 0xd3, 0xaf, 0x01, 0xe7, 0x13, 0xc0, + 0xd1, 0x85, 0x93, 0x88, 0x8d, 0xf2, 0xd5, 0x2d, 0x30, 0x97, 0x1b, 0x54, + 0xc3, 0x1a, 0xff, 0xf6, 0x05, 0xd7, 0x9b, 0xcb, 0x3f, 0xc0, 0x9d, 0x77, + 0x5c, 0xeb, 0xa6, 0xd1, 0xd7, 0xec, 0xd8, 0x82, 0x1c, 0x35, 0x9f, 0x45, + 0x6f, 0xdd, 0xcd, 0xfd, 0x07, 0x5f, 0xb6, 0x9e, 0x7f, 0xb2, 0x3a, 0xbe, + 0x26, 0x10, 0xc3, 0xae, 0x1f, 0x80, 0x9e, 0xf8, 0x39, 0xd7, 0x3a, 0xff, + 0xe8, 0xc1, 0x97, 0x70, 0x46, 0x19, 0x3a, 0xb8, 0x8a, 0x01, 0x40, 0xf1, + 0x05, 0xfe, 0xe6, 0xbb, 0x82, 0x9a, 0x3a, 0x90, 0xf8, 0x1c, 0xbe, 0xff, + 0xb0, 0x38, 0x30, 0x20, 0x83, 0xae, 0x86, 0x4e, 0xa9, 0xdd, 0x99, 0xf4, + 0xa5, 0xe8, 0x86, 0x5c, 0xae, 0x3e, 0x29, 0x08, 0x06, 0xca, 0xac, 0xdc, + 0xe5, 0x21, 0xb7, 0x31, 0x8f, 0x29, 0xf0, 0xcb, 0x8e, 0x03, 0xb3, 0x80, + 0x0e, 0xa9, 0xfc, 0x27, 0x86, 0x7b, 0x17, 0x51, 0xf2, 0xfa, 0x70, 0x94, + 0x11, 0xbc, 0xec, 0x94, 0x83, 0xf4, 0x83, 0x68, 0xd2, 0xff, 0xb3, 0x83, + 0x1e, 0x96, 0x74, 0xeb, 0xf8, 0x7f, 0xc0, 0xbc, 0x8e, 0xbf, 0xff, 0x03, + 0xda, 0x6f, 0x50, 0x63, 0x7d, 0x22, 0xe0, 0xeb, 0xfc, 0xd1, 0xc9, 0x49, + 0xf4, 0x75, 0xfc, 0xec, 0xe7, 0xff, 0x7c, 0x75, 0xf9, 0xe5, 0xf0, 0x28, + 0x75, 0xe9, 0x47, 0xe7, 0x5f, 0xbe, 0xcd, 0x28, 0x57, 0x2a, 0xa1, 0x38, + 0x8c, 0x36, 0x50, 0xb1, 0x15, 0x38, 0x63, 0xd3, 0x0f, 0x14, 0x7d, 0x1c, + 0xb3, 0x4e, 0xbf, 0xf9, 0x41, 0x03, 0xfd, 0xcd, 0x24, 0x09, 0xd7, 0xb6, + 0xd0, 0x27, 0x57, 0x0f, 0x85, 0x68, 0x77, 0xff, 0x6f, 0xe0, 0x2f, 0xb0, + 0x82, 0xe1, 0x3a, 0xf9, 0x4e, 0x3b, 0x27, 0x5b, 0xe9, 0xa2, 0x05, 0xb7, + 0x8d, 0x40, 0xa5, 0x78, 0xde, 0x32, 0x3f, 0x58, 0x88, 0x14, 0x5f, 0xbf, + 0xf2, 0x6d, 0xf5, 0x3e, 0xb1, 0xff, 0xf0, 0x55, 0xff, 0x0f, 0xb4, 0x0d, + 0xfc, 0x8c, 0x9d, 0x7f, 0x80, 0xfa, 0xcc, 0x15, 0x0e, 0xa8, 0x3e, 0xbe, + 0x9d, 0x5f, 0xfe, 0x45, 0x3e, 0x0b, 0xa9, 0xf3, 0x5f, 0xff, 0x07, 0x5f, + 0xe7, 0xee, 0xfa, 0x81, 0xf1, 0xd5, 0xa4, 0x41, 0x79, 0x42, 0xff, 0x9b, + 0xd4, 0x9a, 0x50, 0x32, 0x3a, 0xfa, 0x5d, 0xc9, 0xce, 0xbf, 0xe8, 0xdd, + 0x6f, 0xec, 0xdf, 0xc7, 0x56, 0xe7, 0xb6, 0x24, 0x57, 0xfd, 0x0d, 0xf0, + 0x3b, 0xc8, 0x64, 0xeb, 0xb8, 0xe7, 0x5f, 0xff, 0xd1, 0xcf, 0xf3, 0x62, + 0x6b, 0x58, 0x2d, 0x71, 0xfc, 0xea, 0xe1, 0xf8, 0x74, 0x56, 0xff, 0xcf, + 0xbe, 0xb3, 0xc8, 0xb7, 0x91, 0xd6, 0xf1, 0xd5, 0xf9, 0xe6, 0xfd, 0x3d, + 0xbf, 0xff, 0xf8, 0x1a, 0xeb, 0xcb, 0x52, 0x4f, 0x7d, 0xe4, 0x76, 0x3d, + 0xa7, 0xdc, 0xeb, 0xf4, 0x60, 0xfb, 0x6c, 0xeb, 0xf9, 0x37, 0xff, 0x8e, + 0x13, 0xac, 0xb3, 0xa9, 0x67, 0xcd, 0xd2, 0x81, 0x2e, 0xbd, 0x20, 0x04, + 0xeb, 0x9f, 0x7f, 0x87, 0x94, 0xe5, 0xd5, 0xc4, 0xd4, 0xf5, 0x19, 0x25, + 0xff, 0xfd, 0x83, 0x3e, 0xb5, 0x1f, 0xe7, 0x53, 0x8e, 0xcf, 0x8e, 0xa0, + 0xae, 0x48, 0x6f, 0x0a, 0x39, 0x88, 0xf9, 0x09, 0x35, 0x91, 0x76, 0x15, + 0x3f, 0xb7, 0xfa, 0x37, 0x86, 0x4a, 0xaa, 0x17, 0x76, 0x92, 0x75, 0x02, + 0xff, 0xff, 0xb9, 0x3e, 0x24, 0xce, 0xf2, 0xd4, 0x2c, 0x3d, 0x81, 0x69, + 0xd7, 0xc1, 0xe8, 0x27, 0x3a, 0xff, 0x05, 0xe5, 0x93, 0x80, 0x4e, 0xb4, + 0xf0, 0x7a, 0xb8, 0x47, 0x72, 0xa7, 0x0e, 0xac, 0x3c, 0x07, 0x27, 0xbf, + 0xbd, 0xb6, 0x0e, 0xe3, 0x4e, 0xbf, 0xdc, 0x8f, 0x27, 0xf1, 0x23, 0xaf, + 0x4e, 0x32, 0x3a, 0x95, 0x0c, 0x91, 0x68, 0x71, 0x42, 0x25, 0xc3, 0x13, + 0xb3, 0xbf, 0x6e, 0x58, 0x30, 0xfa, 0xd1, 0x07, 0x8c, 0x00, 0x65, 0x7f, + 0xe5, 0x47, 0xd8, 0x5b, 0x7a, 0xfb, 0xfe, 0x75, 0xfe, 0x94, 0xd8, 0x2f, + 0xdc, 0x3a, 0xff, 0x6c, 0x79, 0x83, 0x03, 0x39, 0xd7, 0xd0, 0x05, 0x4a, + 0x1d, 0x7b, 0xde, 0x83, 0xaf, 0xf2, 0x72, 0x27, 0x7e, 0x34, 0xeb, 0x7b, + 0x87, 0xe2, 0xe4, 0x9e, 0x1b, 0xbf, 0xfd, 0xc6, 0x8e, 0x6c, 0x1c, 0x8e, + 0x46, 0x8e, 0xbf, 0xcf, 0x37, 0x71, 0x79, 0xa3, 0xab, 0x0f, 0xeb, 0x62, + 0x45, 0xfc, 0x8a, 0x7b, 0x31, 0x67, 0x5f, 0xb0, 0x29, 0xcd, 0x1d, 0x7b, + 0xde, 0xdc, 0xeb, 0xff, 0xb7, 0x6a, 0x77, 0xe6, 0xd6, 0x75, 0x16, 0x75, + 0x7e, 0x7c, 0xde, 0x1d, 0xb8, 0x1c, 0x3a, 0xb4, 0x6e, 0x76, 0xc8, 0xed, + 0x13, 0xa3, 0xa5, 0x98, 0x62, 0xd4, 0x2a, 0xbb, 0xc8, 0x53, 0x24, 0x2b, + 0xba, 0x47, 0xe8, 0xc5, 0x6f, 0xfc, 0x29, 0xf7, 0x7c, 0xd9, 0xbc, 0x7d, + 0x3a, 0xff, 0xf2, 0x67, 0x03, 0x0c, 0xe7, 0x63, 0x7d, 0x1d, 0x7d, 0xf6, + 0x39, 0xf9, 0xd7, 0x3f, 0x0e, 0xbf, 0xbc, 0x93, 0xae, 0x1a, 0x75, 0x04, + 0xf0, 0xba, 0x2b, 0x76, 0x6d, 0x1d, 0x7d, 0xff, 0xd1, 0x91, 0xd7, 0x7e, + 0xe2, 0x6f, 0x3c, 0x31, 0x50, 0x88, 0xa0, 0x2f, 0x5d, 0xbc, 0xc7, 0x5f, + 0xbe, 0xfb, 0xf5, 0xe1, 0xd4, 0xb3, 0xc2, 0xfc, 0x62, 0xf3, 0x63, 0x47, + 0x5f, 0xf4, 0x9f, 0x9e, 0x18, 0x5e, 0x8e, 0xbf, 0xd0, 0x18, 0xe0, 0x23, + 0xf3, 0xae, 0x5e, 0xa6, 0x3e, 0x95, 0x9b, 0xdf, 0xfa, 0x1c, 0x73, 0xde, + 0x46, 0x7c, 0x75, 0x42, 0x62, 0x58, 0x46, 0x90, 0x84, 0x01, 0x7d, 0x2a, + 0x97, 0xaf, 0xa1, 0x1a, 0x52, 0xbb, 0x31, 0x65, 0xa8, 0x93, 0x24, 0xea, + 0x1e, 0x1e, 0x8d, 0xda, 0xfe, 0x80, 0x6e, 0x9b, 0xed, 0x1d, 0x7e, 0xc6, + 0x73, 0x7f, 0x1d, 0x6e, 0x7c, 0x3d, 0x94, 0x31, 0xbf, 0xfd, 0xac, 0x10, + 0x37, 0xb8, 0xb9, 0x9d, 0xa7, 0x5f, 0xe1, 0x53, 0xb0, 0xb5, 0x89, 0xd7, + 0xf2, 0xba, 0x46, 0xd0, 0x3c, 0x75, 0xfa, 0x26, 0xcc, 0x69, 0xd5, 0x88, + 0x8a, 0x43, 0x2e, 0x99, 0x5f, 0xfb, 0xb9, 0x32, 0x4c, 0x0d, 0xa0, 0x68, + 0xeb, 0xc9, 0xc5, 0x0e, 0xa4, 0x3d, 0xf1, 0x43, 0xbf, 0x46, 0xd7, 0x62, + 0x63, 0xaa, 0x47, 0x95, 0xa2, 0x0b, 0xff, 0x81, 0x32, 0x76, 0x37, 0x94, + 0x4d, 0x07, 0x5f, 0x82, 0xe3, 0x1d, 0x3a, 0xfe, 0x94, 0x6f, 0xec, 0xe9, + 0xd7, 0xff, 0xbd, 0xa4, 0xfe, 0x25, 0xac, 0xcd, 0xfc, 0x75, 0x4c, 0x7e, + 0xfa, 0x2d, 0xb2, 0x75, 0x17, 0xec, 0xc2, 0x72, 0xff, 0xfd, 0xc0, 0x73, + 0x90, 0x38, 0xa2, 0x77, 0xb9, 0xf4, 0xeb, 0xf8, 0x5d, 0x03, 0x02, 0x75, + 0xf4, 0xf1, 0xb5, 0x07, 0x5e, 0xd8, 0x0e, 0x9d, 0x7f, 0xf2, 0x2d, 0x35, + 0xd8, 0x4e, 0x01, 0x5c, 0xea, 0x84, 0x43, 0xa1, 0x23, 0x8f, 0x5f, 0xc3, + 0xa4, 0xd9, 0x01, 0x3a, 0xf0, 0xa2, 0x87, 0x5f, 0xde, 0x4e, 0x27, 0x80, + 0x75, 0xa1, 0x67, 0x8f, 0xf4, 0x6e, 0xfe, 0x07, 0xde, 0xe6, 0xfa, 0x3a, + 0xff, 0xff, 0xfd, 0xc8, 0xf0, 0xbb, 0x53, 0x53, 0x27, 0x1b, 0x1a, 0xf4, + 0x6f, 0x1f, 0x73, 0x47, 0x5f, 0xee, 0xe6, 0xf1, 0xc4, 0x59, 0xd7, 0xff, + 0xff, 0xfe, 0xd6, 0xb3, 0xdd, 0x75, 0xeb, 0x9c, 0x4d, 0xfc, 0xee, 0xa6, + 0x64, 0xc0, 0xf4, 0x33, 0xbc, 0x1d, 0x50, 0x9a, 0x88, 0x61, 0x06, 0xe6, + 0x57, 0xdf, 0xbe, 0xfa, 0x3a, 0xe6, 0x59, 0x3a, 0xb4, 0x6e, 0xd9, 0x23, + 0xbf, 0x27, 0x5f, 0x3a, 0x53, 0x06, 0x8a, 0xff, 0x81, 0xe8, 0x16, 0xab, + 0x7f, 0xac, 0xeb, 0xdd, 0x8f, 0xce, 0xa4, 0x3d, 0xa7, 0x3e, 0xbf, 0xdd, + 0x8f, 0x01, 0x60, 0xf1, 0xd5, 0x0b, 0xfd, 0x92, 0x29, 0x0c, 0x34, 0xf7, + 0x86, 0xba, 0xb9, 0x14, 0xd1, 0x82, 0x70, 0xb9, 0x6a, 0xdd, 0x85, 0x83, + 0x96, 0xfe, 0xe8, 0xa9, 0x29, 0x18, 0xe0, 0x75, 0x09, 0x1f, 0x42, 0x43, + 0x68, 0x82, 0xfd, 0x34, 0x4d, 0xd8, 0x3a, 0xef, 0xb0, 0x75, 0xe6, 0x59, + 0x64, 0xab, 0xe9, 0x7b, 0x1a, 0x53, 0x05, 0xfd, 0xfb, 0x02, 0x9f, 0xe8, + 0xf7, 0x7f, 0x57, 0x0f, 0x94, 0x4c, 0x6a, 0x11, 0xc9, 0xc2, 0x87, 0x84, + 0xdd, 0xde, 0xd1, 0xd7, 0xfd, 0xf3, 0xdd, 0x8f, 0x6b, 0xa8, 0x75, 0xb4, + 0x75, 0xfe, 0xf6, 0xf2, 0xec, 0x0c, 0xe7, 0x5f, 0xfb, 0x37, 0x92, 0x60, + 0x8e, 0x04, 0xeb, 0xf4, 0xeb, 0x06, 0xfe, 0x3a, 0xa1, 0x1f, 0x3b, 0x8b, + 0x70, 0xe8, 0x44, 0x34, 0x69, 0xe3, 0xbb, 0xfe, 0x18, 0x67, 0x48, 0x3b, + 0xc8, 0xeb, 0xa1, 0xa7, 0x50, 0x9e, 0x6e, 0xc3, 0x8b, 0xe9, 0xfe, 0xc2, + 0xb9, 0xd7, 0xfb, 0x41, 0x18, 0x67, 0x04, 0xea, 0xe1, 0xec, 0x78, 0x9e, + 0xa1, 0x34, 0x04, 0x85, 0x1b, 0xbd, 0xdf, 0xc3, 0xbe, 0xa6, 0xcf, 0x1d, + 0x7f, 0x27, 0x85, 0xff, 0xd1, 0xd7, 0xff, 0xbd, 0x36, 0x73, 0x1d, 0x71, + 0xd4, 0x09, 0xd7, 0xf0, 0x17, 0x9d, 0xdd, 0xce, 0xa5, 0x11, 0x42, 0x25, + 0x9a, 0x48, 0xbf, 0xfc, 0x81, 0x17, 0xdc, 0x73, 0xd8, 0x9f, 0x9d, 0x7f, + 0x47, 0xbb, 0x2d, 0x00, 0xeb, 0xf7, 0x5f, 0x99, 0xc3, 0xae, 0x03, 0x9d, + 0x4d, 0x37, 0x62, 0x4d, 0x7f, 0x72, 0x12, 0x4f, 0xa3, 0xad, 0x13, 0x9e, + 0x58, 0x90, 0x5f, 0xa7, 0x57, 0x4c, 0xdc, 0xeb, 0xf2, 0x6a, 0x27, 0x59, + 0xec, 0xfd, 0xbf, 0x43, 0xf3, 0xf0, 0x1e, 0xcf, 0xdb, 0x9e, 0x47, 0xb3, + 0xf6, 0xf8, 0x12, 0xcd, 0x1e, 0xcf, 0xda, 0x09, 0xe8, 0x09, 0x15, 0xfa, + 0x33, 0x58, 0x27, 0xb3, 0xf6, 0x8f, 0x67, 0xed, 0xcf, 0xe3, 0xd9, 0xfa, + 0xb2, 0xde, 0xd2, 0x13, 0xf9, 0x02, 0x45, 0xf6, 0x6d, 0xa7, 0xe7, 0xb3, + 0xf6, 0x8f, 0x67, 0xed, 0xdf, 0xc1, 0xec, 0xfd, 0xbf, 0xec, 0xfd, 0xf9, + 0x9b, 0x30, 0x27, 0xb3, 0xf6, 0xfe, 0xce, 0xa6, 0x81, 0x39, 0xec, 0xfd, + 0xaf, 0xd1, 0x46, 0x24, 0x7a, 0x46, 0xbe, 0xe4, 0xf1, 0xe3, 0xd9, 0xfb, + 0x47, 0xb3, 0xf7, 0x0d, 0x7d, 0xcc, 0xb2, 0x7b, 0x3f, 0x6a, 0x4a, 0xc3, + 0x82, 0x69, 0x90, 0x84, 0xde, 0x13, 0x5c, 0x27, 0x59, 0x8e, 0xa1, 0x75, + 0xe5, 0xf6, 0x49, 0xaf, 0x4a, 0x14, 0x2d, 0x9f, 0xa6, 0x11, 0x21, 0x7f, + 0xb5, 0x92, 0x94, 0x7b, 0x73, 0xab, 0x0f, 0xc3, 0x47, 0xb7, 0xfe, 0xc6, + 0x87, 0x38, 0xcb, 0xf6, 0x63, 0xae, 0x94, 0xe5, 0x5f, 0x4c, 0xef, 0xc3, + 0xaa, 0x74, 0x4c, 0x6e, 0x42, 0x27, 0xfb, 0x42, 0xf5, 0xc5, 0xd1, 0x27, + 0x9c, 0xd1, 0xbf, 0xcb, 0xd0, 0xe7, 0xb3, 0xf3, 0xaf, 0xf9, 0xb1, 0xf8, + 0x40, 0xfc, 0x91, 0xd7, 0xfe, 0x77, 0x9f, 0x16, 0xe3, 0xbc, 0x8e, 0xbf, + 0x32, 0x2e, 0xa6, 0xb0, 0xfd, 0xa6, 0x39, 0xa8, 0x47, 0x43, 0xc2, 0xa2, + 0xfc, 0x3e, 0xee, 0x4e, 0x75, 0xc1, 0x64, 0xea, 0x83, 0x7d, 0x84, 0xf7, + 0xff, 0xe9, 0x72, 0x36, 0x3c, 0xd0, 0x1e, 0xc2, 0xde, 0x63, 0xaf, 0xf6, + 0xd3, 0xe9, 0x35, 0x36, 0x1d, 0x5b, 0xa2, 0x33, 0x8a, 0xf5, 0x0c, 0xc1, + 0x99, 0x4a, 0x6c, 0xc3, 0x34, 0x86, 0x7a, 0xb9, 0x87, 0x11, 0xfb, 0x0b, + 0x37, 0x9d, 0x39, 0x18, 0xc5, 0x74, 0xc8, 0x08, 0x55, 0xdf, 0xff, 0xf2, + 0x75, 0xfb, 0x12, 0x63, 0x3f, 0x89, 0x68, 0x3d, 0x8e, 0x1d, 0x7f, 0xe5, + 0x23, 0x71, 0x8e, 0xf4, 0x0d, 0x3a, 0xff, 0xf0, 0x79, 0x18, 0x39, 0x24, + 0xee, 0x6c, 0x3a, 0xfe, 0x17, 0x53, 0xaf, 0x23, 0xaf, 0x32, 0xcb, 0x25, + 0x5e, 0xfb, 0x1f, 0x94, 0xc1, 0x7f, 0x7f, 0xcf, 0x2f, 0xbc, 0xcd, 0x8f, + 0xc3, 0xaf, 0xff, 0xdd, 0xc9, 0x7d, 0x11, 0xc9, 0xe6, 0x94, 0x72, 0x73, + 0xa8, 0x51, 0x27, 0xe3, 0xbb, 0xfe, 0xf3, 0x8e, 0x6b, 0x91, 0xa3, 0xaf, + 0xa5, 0x1f, 0xee, 0x75, 0xfd, 0xfc, 0x0e, 0x6f, 0xe3, 0xae, 0x7f, 0xfe, + 0x1e, 0x87, 0xd2, 0x3a, 0x74, 0x5c, 0x0c, 0x21, 0xaf, 0x6c, 0x8e, 0x1d, + 0x52, 0x56, 0x2c, 0x16, 0x6c, 0x3f, 0x5a, 0x47, 0xe9, 0x63, 0x0c, 0x1f, + 0x43, 0x6b, 0x61, 0x35, 0xc9, 0x39, 0xd7, 0xf8, 0x5a, 0x14, 0xd9, 0x01, + 0x3a, 0x82, 0x79, 0x20, 0x16, 0xb7, 0xe7, 0x5f, 0xf6, 0x42, 0xbf, 0xce, + 0xbe, 0x70, 0xeb, 0xfd, 0xfe, 0xda, 0x2c, 0x21, 0xc3, 0xaf, 0xfb, 0xdd, + 0xcd, 0x7c, 0xf2, 0x4e, 0x75, 0x41, 0xf8, 0xa1, 0xb5, 0xff, 0x0a, 0x01, + 0x53, 0xad, 0xb8, 0xf1, 0xd5, 0x24, 0xc6, 0xe6, 0x11, 0xec, 0x2b, 0x04, + 0x82, 0xf3, 0x2c, 0xb2, 0x58, 0x84, 0x17, 0xcd, 0x77, 0x69, 0x62, 0x10, + 0x30, 0x6b, 0x6f, 0x9f, 0x98, 0xc9, 0xd5, 0xc3, 0xe0, 0xd8, 0x7f, 0x79, + 0x96, 0x59, 0x2c, 0x41, 0xea, 0x2c, 0x41, 0xe6, 0x0d, 0x6d, 0xe6, 0x59, + 0x64, 0xeb, 0xda, 0x85, 0x0a, 0x60, 0xbf, 0xb2, 0xf1, 0x18, 0xad, 0x51, + 0xf2, 0x45, 0xff, 0xdd, 0x89, 0x27, 0xb3, 0xad, 0x85, 0x9d, 0x50, 0x7e, + 0xfb, 0x0d, 0x6f, 0xff, 0x67, 0x53, 0x9d, 0x7c, 0xd2, 0x3c, 0xe7, 0x5f, + 0x47, 0xa1, 0x67, 0x52, 0xcf, 0x9f, 0xc8, 0xf7, 0xf3, 0x2e, 0x10, 0x3f, + 0xd3, 0xaf, 0x85, 0x21, 0x43, 0xaf, 0x7d, 0x8f, 0xce, 0xa9, 0xcd, 0xf2, + 0xc8, 0x2f, 0xcd, 0x8e, 0xc2, 0xca, 0xbf, 0x0b, 0x88, 0xe1, 0x57, 0x63, + 0x4a, 0xb9, 0x96, 0x4a, 0xac, 0x3f, 0x6d, 0x13, 0x78, 0x8d, 0x91, 0x5b, + 0xfc, 0x3f, 0x63, 0xfe, 0xe6, 0xd1, 0x4c, 0x1b, 0xcb, 0xff, 0xd3, 0x87, + 0x8e, 0xd1, 0xcd, 0x9c, 0x4d, 0x1d, 0x50, 0x9f, 0xb6, 0x11, 0x23, 0x6b, + 0xc3, 0x50, 0x09, 0x17, 0xff, 0x47, 0xfa, 0xcc, 0x0b, 0x8b, 0xa8, 0x75, + 0xff, 0xf4, 0xb4, 0xcc, 0x73, 0xb0, 0x9d, 0x81, 0x43, 0xaf, 0xff, 0xb4, + 0x39, 0xbf, 0xef, 0xa7, 0xe2, 0x6f, 0xf9, 0xd5, 0xba, 0x27, 0x99, 0x4d, + 0xae, 0xa6, 0x0a, 0xf0, 0xe0, 0xbf, 0xb5, 0xf4, 0x20, 0x19, 0x1d, 0x7f, + 0x23, 0x43, 0x8f, 0xf9, 0xd7, 0xff, 0xfe, 0x89, 0xd8, 0xd7, 0xb5, 0xbf, + 0xc0, 0xe0, 0x61, 0xf9, 0x83, 0xf9, 0xd7, 0xe5, 0xe9, 0x97, 0xdc, 0xeb, + 0x68, 0x28, 0x99, 0xfa, 0xe1, 0x7f, 0x64, 0xd2, 0x4e, 0x68, 0xea, 0x86, + 0x4a, 0xa8, 0x61, 0x8f, 0x91, 0x9e, 0xa4, 0xa0, 0xce, 0x4a, 0x80, 0x78, + 0xd4, 0x55, 0x25, 0x02, 0x5f, 0xa8, 0x62, 0xf8, 0xae, 0xf3, 0x2c, 0xb2, + 0x55, 0xf7, 0xee, 0x21, 0x29, 0x82, 0xfe, 0xfb, 0xa8, 0xf2, 0x3a, 0xfb, + 0x9c, 0x45, 0x9d, 0x7b, 0x51, 0xe3, 0xaf, 0x0f, 0xb4, 0x86, 0xf2, 0x62, + 0x1b, 0xdf, 0x14, 0xdb, 0x3a, 0xf7, 0x9c, 0x27, 0x57, 0x0d, 0xee, 0x88, + 0xaf, 0xe6, 0xc7, 0xe9, 0xc5, 0x0e, 0xbf, 0xbe, 0xe7, 0x33, 0x26, 0x3a, + 0xfc, 0xfd, 0xf8, 0x18, 0x3a, 0xa4, 0x9d, 0x08, 0x4c, 0x71, 0x71, 0x1b, + 0xc4, 0x87, 0x45, 0xde, 0x2e, 0xbf, 0x3f, 0x39, 0x9b, 0x9d, 0x7f, 0xfb, + 0xdd, 0x47, 0xff, 0x38, 0x18, 0x19, 0x1d, 0x7f, 0xfb, 0x7f, 0x9b, 0xff, + 0x02, 0xd7, 0x9c, 0x5c, 0xea, 0x84, 0x5e, 0x61, 0x38, 0xa4, 0x5f, 0xa3, + 0x5f, 0x46, 0x47, 0x5f, 0xff, 0xfc, 0xe9, 0xe4, 0xeb, 0x53, 0xe4, 0x93, + 0xae, 0x3e, 0x96, 0x73, 0x0e, 0xbd, 0xdc, 0xda, 0x3a, 0xfd, 0xed, 0x7d, + 0xd7, 0xce, 0xa2, 0x35, 0xdb, 0xef, 0xe6, 0x75, 0xd7, 0x6c, 0x1d, 0x7f, + 0xff, 0xf2, 0x29, 0xbc, 0xbd, 0x83, 0xed, 0x7c, 0xd6, 0xb3, 0x98, 0x2f, + 0x23, 0xaf, 0xfe, 0x60, 0x23, 0x00, 0x6e, 0x28, 0x9c, 0x3a, 0xec, 0x64, + 0xeb, 0x64, 0x1e, 0xd6, 0x91, 0x2f, 0xf0, 0x7b, 0x13, 0x3b, 0xee, 0x75, + 0xee, 0xff, 0xb0, 0xea, 0xe1, 0xe9, 0x6d, 0x19, 0xd4, 0x91, 0x3a, 0xef, + 0x17, 0xff, 0x67, 0x3f, 0x5a, 0x6b, 0xee, 0xa3, 0x0e, 0xbc, 0xea, 0xfa, + 0x3a, 0xa4, 0x7c, 0x6e, 0x8b, 0x78, 0x38, 0xb3, 0xaf, 0xbf, 0xf6, 0x7e, + 0x75, 0x21, 0xbe, 0xe0, 0xdd, 0xff, 0x37, 0xa3, 0x1b, 0xa4, 0x74, 0xea, + 0x85, 0xd1, 0x69, 0x46, 0x3c, 0x12, 0xdc, 0x85, 0xaa, 0x22, 0x70, 0xb5, + 0xe3, 0x6a, 0x18, 0x42, 0x81, 0x7f, 0xe9, 0x05, 0xff, 0x9d, 0x02, 0x0f, + 0x6a, 0x7c, 0x64, 0xeb, 0xf6, 0xb1, 0x48, 0xd1, 0xd7, 0xf2, 0xbe, 0x90, + 0x77, 0x91, 0xd7, 0xfe, 0x7e, 0x6d, 0xa7, 0x71, 0xf7, 0xfc, 0xeb, 0xff, + 0xf2, 0x7a, 0x17, 0x9b, 0xfa, 0x17, 0xf7, 0x8f, 0xf9, 0xd7, 0xc8, 0x2e, + 0x13, 0xaf, 0xfb, 0x51, 0xcf, 0x43, 0x01, 0x43, 0xaa, 0x48, 0xae, 0x0a, + 0xbe, 0x87, 0xef, 0xff, 0x69, 0x39, 0x12, 0xec, 0x4c, 0x20, 0x50, 0xeb, + 0x9b, 0xb6, 0x75, 0xfc, 0xa7, 0xa3, 0xb1, 0xa3, 0xaf, 0xee, 0xa6, 0xfa, + 0x7d, 0xce, 0xa9, 0x1f, 0xa2, 0x0c, 0xfe, 0x5b, 0x7f, 0xe1, 0x79, 0xba, + 0xfc, 0xe2, 0x04, 0xeb, 0xc1, 0x41, 0x3a, 0xfe, 0x8f, 0x2a, 0x1e, 0x37, + 0x3a, 0xbe, 0x1e, 0x52, 0x0d, 0x54, 0x95, 0x86, 0xe1, 0x3b, 0x4c, 0x12, + 0x1d, 0xf3, 0x18, 0x72, 0x17, 0xcb, 0x2f, 0x66, 0x10, 0xf7, 0xe4, 0x5a, + 0xac, 0xab, 0xd5, 0xb3, 0xaf, 0xbe, 0xc3, 0x3a, 0x3a, 0xef, 0xfc, 0x75, + 0xf7, 0x39, 0x9a, 0x3a, 0xec, 0x98, 0xeb, 0x4b, 0xe1, 0xf9, 0x4e, 0x48, + 0xe2, 0xff, 0x48, 0x6f, 0xc9, 0xe7, 0x1c, 0x3a, 0xfd, 0xc0, 0xe6, 0x09, + 0xd7, 0xff, 0x2b, 0xa6, 0x76, 0x36, 0x6b, 0xb1, 0xb9, 0xd7, 0xf6, 0xfc, + 0x06, 0xfe, 0x91, 0xd4, 0xe8, 0x9d, 0xd1, 0x28, 0x12, 0x2f, 0xfb, 0x07, + 0x99, 0xac, 0x4e, 0x9d, 0x7f, 0xfd, 0x2f, 0x0e, 0x3f, 0x87, 0x3d, 0xec, + 0x64, 0xeb, 0xd3, 0xe6, 0xc3, 0xaf, 0xff, 0x7b, 0x59, 0x37, 0x63, 0x66, + 0x77, 0xb0, 0x75, 0xfd, 0xd0, 0xa6, 0xc8, 0x09, 0xd5, 0x87, 0xf2, 0xe9, + 0x77, 0xd9, 0xe4, 0xd1, 0xd7, 0xf2, 0xb1, 0x30, 0xab, 0x73, 0x80, 0xea, + 0xd1, 0xec, 0xf8, 0x82, 0xa4, 0xaa, 0x90, 0x30, 0xc1, 0x69, 0x7e, 0xe6, + 0xbc, 0x4d, 0x18, 0x4b, 0xf9, 0xe6, 0xf3, 0x39, 0xd3, 0xaf, 0xf6, 0x91, + 0x4e, 0xb8, 0xa1, 0xd7, 0xc9, 0xac, 0x0b, 0x9e, 0x6f, 0x87, 0x2f, 0xfc, + 0xea, 0xff, 0x83, 0x48, 0x3b, 0xc8, 0xeb, 0xff, 0xfb, 0xd9, 0xd4, 0x8f, + 0x27, 0xf1, 0x26, 0x19, 0x65, 0x92, 0xaf, 0xf7, 0x40, 0xeb, 0x0b, 0xac, + 0xea, 0x14, 0x48, 0x79, 0x7a, 0xf8, 0x39, 0x8a, 0x15, 0x7c, 0xff, 0xbf, + 0x8e, 0xbf, 0xee, 0x3b, 0x7e, 0x76, 0x3e, 0x89, 0xd7, 0x81, 0x1c, 0x3a, + 0xef, 0x68, 0x27, 0xad, 0x31, 0xdd, 0xe9, 0x08, 0x0d, 0x10, 0xcd, 0xee, + 0xc4, 0xe7, 0x5e, 0x65, 0x96, 0x4a, 0xbd, 0x82, 0xd2, 0x98, 0x2f, 0xef, + 0xfd, 0x93, 0xe0, 0x5e, 0x43, 0x13, 0x9d, 0x5f, 0x9f, 0x38, 0x95, 0x5f, + 0x38, 0xab, 0x55, 0x51, 0xd7, 0x2b, 0x55, 0x6a, 0x75, 0xfb, 0x3d, 0xe0, + 0x4e, 0x75, 0xa4, 0xad, 0x4f, 0x28, 0x48, 0xaf, 0x3a, 0xbc, 0x1d, 0x7e, + 0xc0, 0xf5, 0xd5, 0xce, 0xbf, 0x0e, 0x06, 0x16, 0x75, 0x42, 0xae, 0x19, + 0xc8, 0x82, 0x43, 0x8e, 0xfb, 0x97, 0xcc, 0x51, 0xc8, 0x51, 0x74, 0x89, + 0xdd, 0x00, 0x5b, 0xb0, 0x75, 0x92, 0x9b, 0xfd, 0x0b, 0xc4, 0xe4, 0xd2, + 0x3a, 0xf7, 0x92, 0x0e, 0xbb, 0x04, 0xea, 0x43, 0x5c, 0x01, 0xab, 0xff, + 0xf7, 0x5f, 0x9a, 0xc4, 0x17, 0xf6, 0x99, 0x81, 0x3a, 0xfc, 0x14, 0xe4, + 0x78, 0xeb, 0xb7, 0xfc, 0xeb, 0xf9, 0x71, 0xaf, 0xd1, 0xa7, 0x5e, 0xd4, + 0x29, 0xf9, 0xe2, 0xe8, 0x62, 0xff, 0x03, 0x39, 0xff, 0xe8, 0x27, 0x5f, + 0xfb, 0x16, 0x81, 0xe6, 0x05, 0xd6, 0x75, 0xf6, 0x2f, 0xe8, 0x4e, 0xae, + 0x9e, 0xf8, 0x9e, 0x5f, 0xfe, 0x40, 0xf7, 0xee, 0xb3, 0x8d, 0x77, 0x69, + 0xa2, 0x0c, 0xbe, 0x07, 0x71, 0xa7, 0x54, 0x8f, 0xe3, 0x6d, 0x5e, 0xf7, + 0x40, 0xae, 0x75, 0xff, 0xee, 0x3e, 0xcc, 0x16, 0xf5, 0x3f, 0xfb, 0xe3, + 0xaa, 0x11, 0x22, 0xa9, 0x25, 0x00, 0xfd, 0x6e, 0xa8, 0x93, 0xa6, 0xba, + 0x84, 0x97, 0xa3, 0x2a, 0xbf, 0xdf, 0xa7, 0x7b, 0x9f, 0xb9, 0xd7, 0xff, + 0xfc, 0xbc, 0xf7, 0x9f, 0x83, 0x1b, 0xcb, 0xef, 0x3f, 0x5a, 0x68, 0xeb, + 0xfe, 0x5a, 0x33, 0x82, 0x1e, 0xc1, 0xd7, 0x74, 0x07, 0x5f, 0xff, 0xa4, + 0x82, 0x1e, 0xe6, 0xff, 0x5c, 0x7c, 0x21, 0x3a, 0xf2, 0x32, 0xae, 0x75, + 0xfe, 0xcd, 0x9a, 0xf7, 0xa1, 0x67, 0x57, 0x0f, 0x4f, 0xa3, 0xf5, 0x09, + 0xc0, 0x63, 0x4a, 0x1b, 0xcc, 0x2d, 0xa8, 0x54, 0x5f, 0xed, 0xbc, 0xd6, + 0xde, 0x72, 0x0e, 0xbf, 0xfe, 0x18, 0x6f, 0xce, 0x62, 0x01, 0x53, 0x9b, + 0x58, 0x75, 0x49, 0x77, 0x64, 0x24, 0x18, 0xa4, 0x92, 0xa3, 0xff, 0x4b, + 0xd4, 0x76, 0x7e, 0x4e, 0xda, 0x37, 0xbf, 0xda, 0xd6, 0x0f, 0xfb, 0x78, + 0x75, 0xf0, 0xa6, 0xd4, 0x1d, 0x69, 0x8e, 0xbf, 0xb5, 0x83, 0xfe, 0xde, + 0x1d, 0x6d, 0x9f, 0x11, 0x2f, 0x86, 0xbf, 0x91, 0x68, 0x46, 0xff, 0x81, + 0xef, 0xc0, 0xb8, 0xcf, 0x1d, 0x7f, 0xf8, 0x67, 0xf9, 0x32, 0x0e, 0x07, + 0x05, 0x43, 0xaf, 0xe4, 0xdf, 0x6b, 0xb1, 0xe3, 0xaf, 0x7d, 0xc8, 0x3a, + 0xa1, 0x12, 0xea, 0xe9, 0x6e, 0x61, 0x7f, 0xff, 0xe7, 0x0e, 0x0b, 0xfb, + 0x59, 0xcf, 0xff, 0x8c, 0xdf, 0xda, 0x43, 0xaf, 0x47, 0x26, 0x3a, 0xbe, + 0x36, 0xbb, 0x31, 0x2d, 0x32, 0x78, 0x41, 0x06, 0x15, 0x39, 0x2b, 0xa9, + 0xb0, 0xbd, 0xdc, 0xdd, 0x25, 0xd9, 0xf6, 0x15, 0xef, 0x3c, 0x73, 0xfc, + 0x63, 0x42, 0x8e, 0x08, 0x68, 0x32, 0x63, 0xb6, 0xd7, 0x7b, 0x79, 0xf6, + 0x1d, 0x7f, 0x7c, 0x6f, 0x63, 0x7d, 0xa3, 0xaf, 0x7c, 0xfd, 0x93, 0xab, + 0x73, 0xd3, 0xf1, 0x9d, 0xfd, 0x8c, 0xe6, 0x0a, 0x87, 0x5f, 0x2d, 0xf3, + 0x47, 0x52, 0x1e, 0x63, 0x96, 0x5f, 0xff, 0x36, 0x35, 0xa8, 0x5e, 0x79, + 0x35, 0xd7, 0x3a, 0xff, 0x08, 0xc4, 0x97, 0x08, 0x75, 0xfe, 0xf2, 0x6c, + 0x4f, 0x4a, 0x0a, 0xb2, 0xce, 0xbf, 0xb0, 0x54, 0xe4, 0x30, 0x87, 0x87, + 0xf4, 0xce, 0xb1, 0x30, 0x54, 0x4d, 0xd3, 0x95, 0xf7, 0x01, 0xbc, 0x8e, + 0xbf, 0xc3, 0x21, 0xc5, 0xc3, 0x4e, 0xbc, 0xb0, 0xe1, 0xd5, 0x07, 0xdd, + 0x84, 0x6e, 0x61, 0x7b, 0x6c, 0x1e, 0x3a, 0xff, 0xf7, 0xa1, 0x68, 0x1c, + 0x15, 0x3b, 0x0b, 0x3a, 0x9a, 0x7c, 0xfe, 0x1f, 0xbf, 0xfe, 0x4f, 0x76, + 0x35, 0x1d, 0x84, 0x9e, 0x14, 0x3a, 0xfd, 0xef, 0x69, 0xff, 0x3a, 0xfd, + 0x0b, 0xf6, 0x34, 0xeb, 0x92, 0x73, 0xaa, 0x11, 0x64, 0x89, 0xdd, 0x28, + 0xf1, 0x35, 0xf9, 0x94, 0x0e, 0xd2, 0x1d, 0x7f, 0xdd, 0x89, 0x20, 0xe2, + 0xe0, 0xeb, 0xfe, 0xcf, 0x77, 0x16, 0x2f, 0xe3, 0xaf, 0xed, 0x89, 0xcd, + 0xe1, 0x5c, 0xeb, 0x08, 0x4f, 0xa3, 0x0d, 0xaf, 0xcb, 0x86, 0xce, 0x13, + 0xaf, 0xa5, 0x0b, 0x73, 0xaf, 0xdc, 0xfd, 0x69, 0xa3, 0xae, 0xf6, 0xb0, + 0xfc, 0x1c, 0xa3, 0xe9, 0x05, 0x42, 0x34, 0x41, 0x09, 0x6b, 0x68, 0xeb, + 0xfa, 0x27, 0xc1, 0x45, 0x0e, 0xae, 0x1b, 0xcd, 0x08, 0x5f, 0xfd, 0x02, + 0xfd, 0x8f, 0xd8, 0xe6, 0xb4, 0x55, 0x4e, 0xa8, 0xd8, 0x31, 0xb7, 0x63, + 0x1a, 0xc8, 0x6f, 0xf3, 0x87, 0x5a, 0x8e, 0x48, 0xeb, 0x81, 0x39, 0xd7, + 0xfb, 0x79, 0x6f, 0xa4, 0xf4, 0x1d, 0x79, 0x37, 0xd1, 0xd5, 0x87, 0xa0, + 0x86, 0x94, 0x88, 0x87, 0xeb, 0x3d, 0xd8, 0xd3, 0xaf, 0x73, 0x34, 0x77, + 0x8b, 0x5b, 0xff, 0xe0, 0xfc, 0x74, 0xcd, 0x44, 0xf8, 0x28, 0xa1, 0xd7, + 0xfb, 0x8b, 0x8d, 0xfc, 0xed, 0x3a, 0xb1, 0x10, 0x48, 0x9f, 0x7c, 0x8b, + 0x89, 0x8e, 0xbe, 0xc9, 0xc1, 0x23, 0xaa, 0x63, 0xc3, 0x64, 0x86, 0xf8, + 0x01, 0x0c, 0x1d, 0x50, 0x78, 0xae, 0x49, 0x76, 0x32, 0x75, 0x15, 0x7f, + 0x6b, 0xec, 0x72, 0x16, 0x55, 0x15, 0x45, 0x51, 0x54, 0x55, 0x48, 0xf8, + 0x10, 0x2b, 0xf2, 0xe0, 0x05, 0x6d, 0x85, 0x6d, 0x05, 0x5d, 0xdc, 0x2a, + 0xfe, 0x77, 0xf4, 0xd0, 0xb2, 0xbe, 0x16, 0xb6, 0x54, 0x95, 0x45, 0x51, + 0x55, 0x22, 0xd1, 0x02, 0xa8, 0xaa, 0x2a, 0x8a, 0xa2, 0xa8, 0xaa, 0x2a, + 0xa7, 0x37, 0x81, 0x0a, 0x40, 0xaf, 0xc2, 0xb4, 0x15, 0xb0, 0x2a, 0x8a, + 0xa2, 0xaa, 0x45, 0xa6, 0x82, 0xa8, 0xaa, 0x2a, 0x8a, 0xa2, 0xaa, 0x46, + 0xa3, 0xf0, 0xaf, 0x05, 0x6d, 0x05, 0x51, 0x54, 0x55, 0x15, 0x45, 0x54, + 0xe6, 0xa1, 0x40, 0xae, 0x05, 0x74, 0x2a, 0xca, 0x15, 0x45, 0x51, 0x54, + 0x55, 0x15, 0x41, 0x35, 0x1b, 0x85, 0x7e, 0x14, 0x00, 0xaa, 0x2a, 0x8a, + 0xa2, 0xaf, 0xdd, 0x8f, 0xf5, 0x85, 0x51, 0x55, 0x23, 0xcf, 0x68, 0x57, + 0x42, 0x9c, 0x2b, 0xf2, 0x7b, 0x34, 0xaa, 0x2a, 0x8a, 0xa2, 0xa8, 0xaa, + 0x91, 0xa8, 0xdc, 0x29, 0x02, 0xb6, 0x05, 0x51, 0x54, 0x55, 0x15, 0x45, + 0x54, 0x8d, 0x40, 0x42, 0xba, 0x14, 0x21, 0x56, 0xe9, 0x54, 0x55, 0x15, + 0x69, 0x15, 0x45, 0x6e, 0x58, 0x51, 0x54, 0x55, 0x15, 0x45, 0x54, 0xe7, + 0xcd, 0x20, 0xa5, 0x06, 0x9a, 0x35, 0x30, 0x57, 0xe1, 0x5e, 0x0a, 0xb6, + 0x15, 0x45, 0x51, 0x56, 0x91, 0x54, 0x56, 0xe5, 0x85, 0x15, 0x45, 0x54, + 0x1e, 0x94, 0x82, 0x90, 0x6b, 0x83, 0x4b, 0x0a, 0xa2, 0xa8, 0xaa, 0x2a, + 0x8a, 0xa2, 0xaa, 0x0d, 0x96, 0xe1, 0x5c, 0x0a, 0x58, 0x50, 0x85, 0x51, + 0x54, 0x55, 0x15, 0x5c, 0x2f, 0xb4, 0x15, 0xe0, 0xaa, 0x2a, 0x8a, 0xa2, + 0xa9, 0x65, 0xf0, 0x85, 0x78, 0x2a, 0xcb, 0x2a, 0x8a, 0xa2, 0xab, 0xf2, + 0xd0, 0x01, 0x54, 0x55, 0x15, 0x45, 0x51, 0x55, 0x06, 0xa2, 0x60, 0xae, + 0x85, 0x00, 0x2a, 0xa1, 0x7e, 0xa6, 0x77, 0x19, 0x1e, 0x84, 0xa3, 0x16, + 0xda, 0xd9, 0xba, 0x42, 0x33, 0xab, 0x9e, 0xcc, 0x73, 0xc8, 0x46, 0x2d, + 0x27, 0xa7, 0x0e, 0xcb, 0xf9, 0xd0, 0xbb, 0x69, 0x9f, 0xcc, 0x20, 0x79, + 0xd8, 0xca, 0xca, 0x5e, 0xd9, 0x67, 0xd2, 0x4d, 0xa4, 0x9b, 0xf4, 0x86, + 0x33, 0x45, 0x30, 0x9a, 0xb5, 0xe4, 0x85, 0x95, 0x7c, 0x8d, 0x7e, 0x1d, + 0x79, 0x03, 0x87, 0x59, 0x8d, 0xd1, 0x1b, 0xc3, 0x9e, 0x8d, 0x78, 0x82, + 0xd1, 0xb1, 0x94, 0x8f, 0xf6, 0x94, 0x05, 0x7f, 0xba, 0x8c, 0x87, 0x91, + 0x39, 0xd7, 0x93, 0x62, 0xa4, 0xea, 0xdd, 0x11, 0xd3, 0x1c, 0xf8, 0xd2, + 0xfd, 0x99, 0x33, 0xfd, 0x3a, 0xef, 0xe0, 0xeb, 0xfb, 0x8e, 0x3f, 0x63, + 0xf3, 0xae, 0x7e, 0x1d, 0x64, 0x39, 0xa5, 0xad, 0x9a, 0x75, 0x96, 0x75, + 0xdb, 0x6c, 0x22, 0x25, 0xf8, 0x2d, 0xd4, 0x37, 0x1e, 0xfa, 0x21, 0x7f, + 0xdd, 0x85, 0xe4, 0xd0, 0x33, 0x9d, 0x7f, 0xf7, 0xc7, 0x68, 0x7b, 0x1f, + 0xe0, 0xfe, 0x75, 0xdf, 0xc1, 0xd5, 0x87, 0xb9, 0xfa, 0x35, 0x62, 0x62, + 0x1f, 0xad, 0x02, 0x12, 0x97, 0xff, 0x08, 0xc4, 0xe3, 0x89, 0xb2, 0x36, + 0xce, 0xbd, 0x1b, 0xe8, 0xea, 0x73, 0xe1, 0xd2, 0x2d, 0xe7, 0xe4, 0x1d, + 0x7e, 0x4d, 0xb7, 0x1f, 0xce, 0xa9, 0x1e, 0x1a, 0xc6, 0xaf, 0xfb, 0xeb, + 0x87, 0x58, 0xb8, 0x57, 0x3a, 0xf6, 0x6e, 0xc9, 0xd7, 0xb7, 0xff, 0x38, + 0x7b, 0x22, 0x79, 0x7d, 0xb3, 0x39, 0x23, 0xaf, 0x05, 0xc4, 0xea, 0x43, + 0x7a, 0xe4, 0x77, 0xff, 0xd1, 0xf1, 0xf9, 0xc7, 0xfe, 0x18, 0x65, 0x96, + 0x4e, 0xa8, 0x4d, 0x81, 0xde, 0xf4, 0xe2, 0x01, 0xfa, 0x54, 0x37, 0x17, + 0xb0, 0xe7, 0x3b, 0x7c, 0xa3, 0x25, 0x0c, 0x27, 0x72, 0x12, 0x6d, 0x86, + 0xa6, 0xe7, 0x69, 0x29, 0x81, 0x5d, 0x16, 0x68, 0x5c, 0xf0, 0xdd, 0x70, + 0xac, 0xec, 0x2a, 0x5e, 0x95, 0xeb, 0xf9, 0x90, 0xc7, 0x9f, 0xa8, 0x4b, + 0xfa, 0x3c, 0x4b, 0xe4, 0x16, 0xc1, 0xd7, 0xf3, 0x2f, 0xce, 0x3e, 0xe7, + 0x5f, 0xff, 0xb5, 0xce, 0x24, 0xda, 0xe4, 0x79, 0x1a, 0x81, 0x3a, 0x96, + 0x8a, 0x21, 0x1f, 0x64, 0xba, 0xf9, 0x7e, 0x8d, 0x1d, 0x7f, 0xbd, 0x00, + 0x6f, 0x53, 0x87, 0x5f, 0xd8, 0xde, 0xc6, 0xf2, 0x3a, 0xfe, 0x5e, 0x91, + 0x4f, 0x32, 0x75, 0xfa, 0x37, 0xec, 0x48, 0xea, 0x14, 0x5a, 0xf8, 0xcb, + 0xe9, 0x6e, 0xd1, 0x7d, 0xdb, 0xf8, 0xeb, 0xf7, 0x9c, 0x41, 0x87, 0x5f, + 0xed, 0x62, 0xd3, 0xdd, 0x73, 0xad, 0x18, 0x7d, 0xa2, 0x2f, 0xe2, 0x5b, + 0xe9, 0x7c, 0x5a, 0x1d, 0x7b, 0x6b, 0x90, 0x75, 0xfe, 0xe2, 0x4c, 0x39, + 0xb1, 0xce, 0xbb, 0x7d, 0x7c, 0x3f, 0x48, 0x23, 0xe0, 0xf5, 0xff, 0x0c, + 0x3c, 0xfd, 0x8e, 0x7e, 0x75, 0xcf, 0xb0, 0xeb, 0xfa, 0x42, 0x92, 0xee, + 0x1d, 0x7e, 0x9d, 0x39, 0x12, 0x3a, 0xa6, 0x3e, 0x9e, 0x0b, 0x89, 0x5d, + 0xf6, 0x05, 0x14, 0x3a, 0xff, 0xf3, 0xa7, 0xa3, 0xda, 0xeb, 0xa7, 0x40, + 0x75, 0xf0, 0x88, 0x24, 0x75, 0xff, 0xbb, 0x1c, 0xfc, 0x71, 0x97, 0xfc, + 0xeb, 0xd9, 0x93, 0x1d, 0x6c, 0xe9, 0xed, 0x7e, 0x7f, 0x7f, 0x03, 0x80, + 0x5b, 0x89, 0xd7, 0xcb, 0x8c, 0x9c, 0xeb, 0xf6, 0x6c, 0x18, 0xdc, 0xea, + 0x43, 0xc9, 0xd1, 0x0d, 0xf4, 0x0f, 0x9a, 0x75, 0xa0, 0x2a, 0xa4, 0x32, + 0x14, 0x3c, 0x2f, 0xe9, 0x0b, 0xa3, 0x8b, 0xd6, 0x8a, 0x3c, 0xeb, 0xb6, + 0x43, 0x7f, 0x6b, 0x16, 0x9d, 0x83, 0xaf, 0x6f, 0x2d, 0x1d, 0x5b, 0x9e, + 0x47, 0x0a, 0xef, 0x6b, 0xf6, 0x4e, 0xa8, 0x3c, 0x1c, 0x23, 0xbe, 0x03, + 0xf2, 0x47, 0x5f, 0x40, 0x15, 0x3a, 0x2a, 0xfd, 0x26, 0x19, 0x65, 0x93, + 0xa8, 0x4f, 0x44, 0x04, 0xb7, 0xcf, 0xe5, 0xf8, 0xea, 0x0a, 0x2d, 0x31, + 0xcb, 0xf2, 0x1a, 0x85, 0xf3, 0xec, 0x30, 0x48, 0x6b, 0x2e, 0x15, 0xcf, + 0x0a, 0x6f, 0xe5, 0x66, 0x8c, 0x62, 0x60, 0x86, 0xa5, 0xe5, 0x65, 0x57, + 0xaa, 0x0e, 0xbd, 0x21, 0x73, 0xad, 0xba, 0xb2, 0x78, 0xb0, 0x57, 0x7f, + 0x47, 0x27, 0x8e, 0x4e, 0x75, 0xf8, 0x1f, 0xe0, 0xb4, 0xeb, 0xdc, 0x89, + 0x8e, 0xbe, 0x41, 0x79, 0x8e, 0xbf, 0xde, 0xcf, 0xb1, 0x32, 0x68, 0xea, + 0x92, 0x31, 0x78, 0x5c, 0xb2, 0x7e, 0x8e, 0x6c, 0x20, 0xbf, 0xe8, 0x4e, + 0xc2, 0xe7, 0xc6, 0x4e, 0xbf, 0xa3, 0xa9, 0x3b, 0x89, 0xd7, 0xfd, 0x38, + 0xe4, 0xbb, 0x9f, 0xe8, 0xeb, 0xff, 0x60, 0xef, 0x2d, 0x70, 0x11, 0xf9, + 0xd7, 0xec, 0xf6, 0xb1, 0x43, 0xa9, 0x0f, 0x99, 0x67, 0xf7, 0x83, 0x1b, + 0x0e, 0xbf, 0xfe, 0xc1, 0x18, 0x64, 0x23, 0x1b, 0xc9, 0x04, 0xeb, 0xff, + 0xcf, 0xf2, 0x69, 0x47, 0x27, 0xf8, 0xce, 0x74, 0xea, 0x0a, 0x2e, 0x7a, + 0x3a, 0x29, 0x97, 0xfc, 0xbe, 0xe7, 0xb0, 0x1c, 0x9c, 0xeb, 0xfe, 0x8f, + 0x67, 0x1a, 0xee, 0xd3, 0x45, 0xf1, 0x7e, 0xce, 0x46, 0xf2, 0x3a, 0xf7, + 0x61, 0x6d, 0x3e, 0xaf, 0x21, 0xdf, 0xff, 0x85, 0xbf, 0x3b, 0x09, 0xc4, + 0x5a, 0x6d, 0xc2, 0xce, 0xbc, 0xfc, 0x9c, 0xd1, 0x7f, 0xd4, 0x22, 0xcf, + 0x0c, 0xda, 0xaf, 0x7f, 0xff, 0xba, 0xfa, 0x48, 0xd7, 0xcf, 0x77, 0x17, + 0x8d, 0x7e, 0x1d, 0x74, 0x6d, 0x1d, 0x7d, 0xad, 0x3a, 0xce, 0xae, 0xa2, + 0x67, 0xf6, 0x0f, 0x0c, 0x5f, 0xff, 0xd2, 0x70, 0xb7, 0xa8, 0x39, 0xb1, + 0xe5, 0xa4, 0x09, 0xd7, 0xfd, 0x0b, 0xf8, 0x1c, 0xcf, 0xf4, 0x75, 0xff, + 0x26, 0x08, 0x54, 0x4c, 0xe1, 0xd4, 0x87, 0xe1, 0xb4, 0x75, 0x7f, 0x3f, + 0x37, 0x96, 0x78, 0xeb, 0xff, 0x7b, 0x49, 0xcf, 0x08, 0x1e, 0x47, 0x5f, + 0xfe, 0x5c, 0x6d, 0xe0, 0x07, 0x33, 0x64, 0x6e, 0x75, 0xff, 0xa3, 0x39, + 0x9c, 0xfd, 0x69, 0xa3, 0xaf, 0x3e, 0xfb, 0x47, 0x5f, 0xcf, 0xed, 0x46, + 0x4e, 0x75, 0x42, 0x67, 0xd8, 0x5a, 0x87, 0xa2, 0x99, 0xb0, 0xf5, 0x91, + 0xfb, 0xfe, 0x04, 0x2f, 0x58, 0xb8, 0x57, 0x3a, 0xff, 0xed, 0x60, 0xfb, + 0x5f, 0x76, 0x46, 0x6e, 0x75, 0xff, 0x33, 0xf6, 0x7d, 0x62, 0xe1, 0x5c, + 0xeb, 0xc9, 0xd4, 0x3a, 0xfa, 0x5c, 0x0c, 0x8e, 0xbe, 0x5f, 0x92, 0x73, + 0xab, 0x0f, 0x11, 0x08, 0xaf, 0xfe, 0xd9, 0xe5, 0x20, 0x65, 0x9d, 0x45, + 0x9d, 0x74, 0xfe, 0x3a, 0xff, 0x6c, 0xeb, 0xca, 0x30, 0x4e, 0xa8, 0x3c, + 0x9c, 0x17, 0xbf, 0xb1, 0x9f, 0xbd, 0x7f, 0x1d, 0x7f, 0xfe, 0xf7, 0xd9, + 0x46, 0xc4, 0x1f, 0xf8, 0x90, 0xbc, 0x2a, 0xfb, 0xbf, 0x77, 0xf1, 0xd7, + 0xec, 0x5e, 0x26, 0xc3, 0xaf, 0x4f, 0x32, 0xb9, 0xd5, 0x3a, 0x3c, 0xf0, + 0xbd, 0xaa, 0xe8, 0x4a, 0x02, 0x7b, 0xbd, 0x87, 0x5f, 0xb8, 0x93, 0xba, + 0xcd, 0x30, 0x9d, 0xf7, 0x81, 0x0e, 0x69, 0x84, 0xee, 0xfe, 0x0d, 0x40, + 0x9d, 0xfe, 0x17, 0x53, 0xd1, 0xcf, 0xcd, 0x40, 0x9d, 0xfe, 0xd6, 0x75, + 0x34, 0x09, 0xcd, 0x30, 0x9d, 0xd8, 0x13, 0x4c, 0x27, 0x73, 0x2c, 0x9e, + 0x61, 0x3a, 0xc4, 0xd2, 0xf7, 0x34, 0x42, 0xd5, 0x91, 0xe9, 0x03, 0x62, + 0x03, 0x24, 0x56, 0xf1, 0x66, 0x13, 0x30, 0x7c, 0xf6, 0x4d, 0xd3, 0xf7, + 0x66, 0x3c, 0x7a, 0x85, 0xcc, 0xf4, 0x3f, 0xea, 0xf3, 0x90, 0x0c, 0x23, + 0xb5, 0x18, 0x9f, 0xa5, 0x20, 0x5e, 0x1f, 0xd6, 0x75, 0xff, 0x40, 0x3c, + 0x29, 0xb3, 0xea, 0xce, 0xbc, 0x39, 0xac, 0x3d, 0x7e, 0x0e, 0x5e, 0x0f, + 0xf3, 0x1d, 0x50, 0xcc, 0xe4, 0x9e, 0x13, 0xe1, 0x86, 0xd6, 0x17, 0xb6, + 0x35, 0x64, 0x86, 0x3c, 0xc6, 0x3c, 0x86, 0x57, 0x63, 0x62, 0x15, 0x7d, + 0x1d, 0x7a, 0x74, 0x5b, 0x64, 0x33, 0x3e, 0x98, 0xdf, 0x83, 0x9c, 0x45, + 0x0e, 0xbf, 0xbb, 0x1f, 0x47, 0x7f, 0xce, 0xbf, 0x7b, 0x26, 0x45, 0x9d, + 0x7e, 0x8d, 0xff, 0xfe, 0x0e, 0xa8, 0x3d, 0x01, 0x27, 0xbf, 0x46, 0xc8, + 0x1f, 0x1d, 0x7e, 0x4d, 0x9e, 0x49, 0xce, 0xbf, 0x3c, 0xbd, 0x8d, 0x3a, + 0xfc, 0x39, 0xf7, 0x26, 0x3a, 0xff, 0xf6, 0x7f, 0xae, 0xa7, 0xcd, 0xe5, + 0x19, 0x39, 0xd7, 0xfd, 0xd7, 0x5f, 0x52, 0x37, 0x91, 0xd7, 0xf7, 0xd1, + 0x96, 0xdb, 0xce, 0x75, 0x49, 0x16, 0xe8, 0x9b, 0xf9, 0xc5, 0x4e, 0x9d, + 0x28, 0x48, 0x1a, 0x4f, 0xc2, 0x91, 0x26, 0xf4, 0x37, 0xef, 0xfd, 0x8f, + 0xd9, 0x90, 0x7b, 0x9b, 0x9d, 0x7f, 0x7f, 0x34, 0xa3, 0xda, 0x3a, 0xff, + 0xff, 0xfd, 0x9d, 0xc1, 0xff, 0x07, 0xdd, 0xce, 0xc6, 0x4c, 0x9c, 0x9b, + 0xa9, 0xbf, 0x8e, 0xbe, 0x18, 0xc6, 0x4e, 0xbe, 0x8d, 0xf4, 0xe7, 0x54, + 0x36, 0x4b, 0xb3, 0xa6, 0x04, 0xe3, 0x29, 0xa1, 0xe9, 0x0f, 0x25, 0x72, + 0x77, 0x94, 0x4a, 0x2b, 0xbe, 0x3d, 0x01, 0x7e, 0xc8, 0x41, 0x7d, 0x20, + 0xbf, 0xfe, 0x41, 0xc5, 0xc7, 0xd1, 0x04, 0x87, 0x16, 0x75, 0xff, 0x05, + 0x30, 0x41, 0x2c, 0xd1, 0xd7, 0xfd, 0xd4, 0x97, 0x5e, 0x48, 0xb3, 0xaf, + 0xfd, 0xa4, 0x1d, 0xe5, 0xe4, 0xd2, 0x1d, 0x58, 0x7e, 0x9e, 0x37, 0xbf, + 0x69, 0x70, 0x18, 0x3a, 0xa4, 0x99, 0xf6, 0x26, 0xae, 0x15, 0x5e, 0x21, + 0xbe, 0x18, 0xe4, 0x8e, 0xbf, 0xee, 0xc4, 0x90, 0x44, 0x1b, 0x9d, 0x7f, + 0xd1, 0x9e, 0xfb, 0xff, 0xf1, 0xb9, 0xd6, 0xe4, 0x22, 0x4f, 0x08, 0x16, + 0x6f, 0x7f, 0xff, 0xfb, 0xae, 0x9e, 0x90, 0x07, 0xda, 0xeb, 0xcb, 0xe8, + 0xc3, 0x79, 0x12, 0x3a, 0xff, 0xda, 0xfb, 0xe4, 0x10, 0x4b, 0x34, 0x75, + 0x2b, 0xa2, 0xdb, 0xae, 0xf7, 0xff, 0xf6, 0x6f, 0x9a, 0x71, 0xea, 0x47, + 0xba, 0x07, 0x59, 0xd5, 0x09, 0xb4, 0x3c, 0x3a, 0x84, 0x9a, 0xfe, 0x10, + 0x2d, 0x3b, 0x07, 0x5f, 0xff, 0x9c, 0x7c, 0xef, 0xd1, 0x8f, 0x69, 0x9c, + 0xe9, 0xd7, 0xfe, 0x9d, 0xc7, 0x5e, 0xea, 0x46, 0x8e, 0xbf, 0xe8, 0xff, + 0x41, 0x03, 0xf2, 0x47, 0x5e, 0xe6, 0xb4, 0x78, 0x80, 0xef, 0x9a, 0xee, + 0xd3, 0x44, 0x06, 0xc1, 0xa9, 0xbf, 0xb9, 0x1d, 0x8f, 0x99, 0x24, 0x50, + 0x71, 0x8a, 0x9d, 0x32, 0x3f, 0xb0, 0xdd, 0xaf, 0xd3, 0x9f, 0xf4, 0x6e, + 0xb7, 0xb6, 0x47, 0x4e, 0xac, 0x54, 0x24, 0x91, 0xe5, 0x7d, 0x2b, 0xbd, + 0xd7, 0x57, 0x3a, 0xfa, 0x3f, 0xdb, 0xc3, 0xab, 0xf3, 0xc2, 0xf0, 0xf5, + 0xf0, 0xfb, 0xf0, 0x1d, 0x7e, 0x5a, 0xb2, 0xac, 0xab, 0x2a, 0xc1, 0xd7, + 0xff, 0xf4, 0xb3, 0x49, 0xce, 0x22, 0xfe, 0xfb, 0xb8, 0xcf, 0x8e, 0xac, + 0x45, 0xda, 0x11, 0x39, 0xe5, 0xff, 0xe6, 0x70, 0x7d, 0x83, 0x2c, 0xd7, + 0xd5, 0x9d, 0x7f, 0xfa, 0x59, 0xbc, 0xbe, 0xc7, 0xec, 0x32, 0xcb, 0x25, + 0x5f, 0x96, 0xce, 0x26, 0xc3, 0xaf, 0x4b, 0x06, 0x63, 0xfb, 0xfa, 0xa5, + 0x50, 0x8f, 0xa7, 0x86, 0x2d, 0x42, 0xa2, 0xbe, 0xc3, 0x78, 0x63, 0x27, + 0xbf, 0xe4, 0x19, 0x69, 0x5a, 0xab, 0x0a, 0xca, 0xb0, 0x75, 0xf4, 0xda, + 0xc9, 0x8e, 0xbf, 0x7f, 0x1e, 0xc5, 0x73, 0xaf, 0xf4, 0x67, 0x1a, 0xee, + 0xd3, 0x44, 0x13, 0x7f, 0xd1, 0xec, 0xe3, 0x5d, 0xda, 0x68, 0xbe, 0x6f, + 0x0e, 0x68, 0x28, 0x80, 0x69, 0xed, 0x0a, 0x37, 0x76, 0x42, 0xaa, 0xff, + 0xe8, 0xea, 0x29, 0x9c, 0x9d, 0x60, 0xdc, 0xea, 0xc4, 0xdb, 0xd2, 0x30, + 0x0e, 0x94, 0xdf, 0xe0, 0x77, 0x6f, 0xa8, 0xde, 0x9d, 0x7f, 0xe9, 0xdf, + 0x7d, 0xbc, 0xf0, 0xbe, 0xc3, 0xaf, 0xff, 0xb3, 0xd0, 0x3e, 0xd6, 0x62, + 0x8a, 0x3c, 0x8e, 0xbf, 0xf6, 0x06, 0x25, 0x1d, 0xcf, 0xdc, 0xeb, 0xf9, + 0xe4, 0x09, 0x38, 0x4e, 0xbc, 0xcb, 0x2c, 0x95, 0x7e, 0xee, 0x35, 0xf8, + 0x53, 0x05, 0xfd, 0xff, 0xfe, 0x9b, 0x91, 0xb3, 0xe2, 0x8f, 0xf3, 0xec, + 0xda, 0xf9, 0x9b, 0xf8, 0xea, 0xf2, 0x29, 0x7e, 0x9b, 0x5f, 0xfe, 0x4e, + 0x27, 0x81, 0x9e, 0x75, 0xe0, 0x9d, 0x53, 0xaa, 0x28, 0x6a, 0x1a, 0xd3, + 0xbf, 0x3c, 0x18, 0x78, 0x78, 0x96, 0xff, 0xcb, 0x8d, 0xf4, 0x39, 0x3f, + 0xd9, 0x1d, 0x7f, 0xff, 0x93, 0xae, 0x3b, 0xcb, 0xec, 0xa0, 0x64, 0xeb, + 0xc0, 0x9d, 0x7f, 0xfb, 0x33, 0xa1, 0xec, 0x6b, 0x3a, 0x9f, 0x9d, 0x7f, + 0x94, 0xf9, 0x34, 0xa3, 0x9a, 0x3a, 0xa7, 0x4c, 0x82, 0x48, 0x21, 0x60, + 0x44, 0x8b, 0xf9, 0x5f, 0x25, 0xd8, 0xe1, 0xd7, 0xfb, 0xd0, 0x9d, 0x52, + 0x37, 0x3a, 0xff, 0xf6, 0xe3, 0xf1, 0xbd, 0x4f, 0xff, 0x8e, 0x48, 0xea, + 0x84, 0x58, 0x21, 0x7f, 0xd3, 0x3b, 0xe5, 0x7d, 0x4b, 0x61, 0xd7, 0xff, + 0xa2, 0x7f, 0xbd, 0x8d, 0xfd, 0x93, 0x88, 0x4e, 0xa7, 0x3f, 0x41, 0x27, + 0xbf, 0xd1, 0x83, 0xe5, 0x43, 0x2d, 0x3a, 0xff, 0x77, 0x36, 0x7c, 0xd4, + 0x9a, 0x75, 0x81, 0xa3, 0xed, 0xf1, 0xb5, 0xfe, 0x71, 0xf9, 0xf7, 0x9d, + 0x73, 0xaf, 0xd9, 0xc7, 0xdd, 0x93, 0xaf, 0xff, 0xf4, 0xf8, 0xc8, 0xe0, + 0x78, 0x80, 0x9c, 0x3d, 0x81, 0x9c, 0xea, 0x9d, 0x11, 0x5a, 0x28, 0xbc, + 0xcb, 0x2c, 0x95, 0x7f, 0xbe, 0xff, 0x03, 0x9b, 0xf8, 0xa6, 0x0b, 0xfb, + 0xff, 0xf9, 0x53, 0xf1, 0xbd, 0x40, 0x87, 0x19, 0xf9, 0xed, 0x64, 0xe7, + 0x57, 0x51, 0x54, 0x04, 0x5a, 0x44, 0xc4, 0x1e, 0x1d, 0xb5, 0x3b, 0x28, + 0x2e, 0x51, 0xde, 0x04, 0xd5, 0x25, 0x2f, 0x72, 0x37, 0xf5, 0xc3, 0xbb, + 0xb0, 0xa4, 0x18, 0x46, 0xe8, 0xa3, 0xd1, 0xe7, 0xdf, 0xfb, 0x10, 0x67, + 0x71, 0xf6, 0x2c, 0xeb, 0xff, 0x75, 0x19, 0x0f, 0x73, 0xdb, 0x78, 0x75, + 0xec, 0x1f, 0xce, 0xbe, 0xcf, 0x4d, 0x23, 0xaf, 0xfe, 0xda, 0x18, 0xda, + 0xd3, 0x8f, 0xdf, 0xf4, 0x75, 0x74, 0xfb, 0x5c, 0x8a, 0xff, 0xd9, 0xe8, + 0xe6, 0xbb, 0x03, 0xe3, 0xc4, 0x11, 0x7f, 0xa3, 0x38, 0xd7, 0x76, 0x9a, + 0x20, 0x86, 0x0f, 0x26, 0xfe, 0x7e, 0xf3, 0x88, 0xc9, 0xd7, 0xf2, 0xb8, + 0x59, 0x71, 0x91, 0xd4, 0x27, 0xba, 0x02, 0xdb, 0xff, 0xf4, 0x06, 0x69, + 0x20, 0xfa, 0x3f, 0x98, 0x52, 0x63, 0xa9, 0x45, 0x42, 0xbd, 0x84, 0x47, + 0xed, 0x43, 0x0a, 0xcd, 0x84, 0x37, 0xf7, 0x73, 0xde, 0x45, 0x9d, 0x7f, + 0x7b, 0xee, 0x75, 0xf7, 0x3a, 0xb7, 0x3d, 0xb1, 0x2c, 0xbf, 0xfd, 0xad, + 0x0b, 0xf9, 0xd7, 0xf6, 0x27, 0xc3, 0xaa, 0x0f, 0xb0, 0x04, 0x57, 0xf6, + 0x37, 0xee, 0xce, 0xe1, 0xd7, 0x42, 0x87, 0x5e, 0x0a, 0x09, 0xd7, 0x84, + 0x13, 0x9d, 0x7e, 0xeb, 0xcb, 0x04, 0xeb, 0xf9, 0x3c, 0x39, 0xd4, 0x3a, + 0xec, 0xef, 0xc3, 0xcf, 0x82, 0x5b, 0x9d, 0x9f, 0x88, 0xc9, 0xc1, 0x6e, + 0x8d, 0x79, 0xae, 0xa4, 0x9b, 0x26, 0x10, 0x8c, 0x3e, 0x6f, 0xff, 0xef, + 0x77, 0x35, 0xac, 0xc0, 0x72, 0x7c, 0x00, 0xf8, 0xeb, 0xfe, 0xec, 0x73, + 0xc3, 0x19, 0xb9, 0xd7, 0xff, 0xfc, 0x93, 0xc4, 0xb5, 0xce, 0x26, 0xf3, + 0x49, 0xf8, 0xbc, 0xdc, 0xeb, 0xdd, 0xc1, 0x0a, 0x28, 0x3a, 0x6f, 0x48, + 0x99, 0x6f, 0xa1, 0xf5, 0x7f, 0xe6, 0xf6, 0x33, 0x92, 0xd0, 0x16, 0x75, + 0xc9, 0xa3, 0xaf, 0xfb, 0x27, 0x7f, 0x7f, 0xf4, 0x64, 0x75, 0xfd, 0xf5, + 0x7a, 0x65, 0xf7, 0x3a, 0xa1, 0x1c, 0xf8, 0x50, 0xa1, 0xf7, 0x05, 0x7c, + 0x77, 0x7b, 0x99, 0xd3, 0xaf, 0x69, 0x16, 0x75, 0xa3, 0x86, 0xdb, 0xc3, + 0x77, 0xc9, 0x32, 0x32, 0x75, 0xff, 0xcb, 0x7d, 0xfe, 0xf9, 0x39, 0x00, + 0x54, 0x9d, 0x7f, 0xfe, 0x04, 0xe3, 0x19, 0xd6, 0x23, 0xd9, 0xd0, 0x70, + 0xeb, 0xef, 0x6b, 0xee, 0x82, 0x8c, 0x1c, 0x22, 0xfa, 0x95, 0x7e, 0xd2, + 0xf3, 0xda, 0x3a, 0xfc, 0xf2, 0x14, 0x83, 0xaf, 0xe8, 0x71, 0xf6, 0x09, + 0xd5, 0x24, 0xe9, 0xb2, 0x1c, 0xe8, 0x96, 0xb2, 0x71, 0x24, 0xbf, 0x9b, + 0xd4, 0xdb, 0x45, 0x0e, 0xbf, 0xfc, 0x9f, 0xc6, 0x97, 0x09, 0xce, 0x23, + 0x27, 0x5f, 0x2b, 0xf7, 0x27, 0x3a, 0xff, 0x40, 0x73, 0xc9, 0xd0, 0x1d, + 0x65, 0xc1, 0xeb, 0x04, 0x96, 0xff, 0xff, 0xcb, 0x71, 0xfe, 0x49, 0xa0, + 0x2f, 0xa9, 0x1e, 0xe8, 0x1d, 0x67, 0x5f, 0xff, 0x08, 0x3d, 0x24, 0xff, + 0xae, 0x9e, 0x75, 0x9d, 0x77, 0xc5, 0x73, 0xaf, 0xff, 0xce, 0x9e, 0x40, + 0xe0, 0x73, 0xc8, 0xb4, 0xe1, 0xd7, 0xb8, 0xfa, 0xc4, 0x5d, 0x71, 0x3b, + 0xa3, 0x77, 0x27, 0x9d, 0x36, 0x50, 0x46, 0x4b, 0x74, 0xa0, 0xeb, 0xff, + 0xd3, 0x87, 0xb1, 0xdc, 0xdf, 0xfc, 0xf6, 0x8e, 0xa7, 0x3e, 0x10, 0x0a, + 0xd0, 0x55, 0x88, 0xe1, 0x82, 0x42, 0x7d, 0xe3, 0x8c, 0x18, 0x4a, 0xdf, + 0xdc, 0x89, 0xd0, 0x7c, 0x75, 0xe0, 0xfd, 0x59, 0xd7, 0xe1, 0x80, 0xe4, + 0xc7, 0x5f, 0x68, 0x1c, 0x50, 0xeb, 0xf4, 0x77, 0xd1, 0x23, 0xaf, 0x82, + 0x0f, 0x6a, 0x0f, 0xbf, 0x72, 0x6f, 0xc8, 0xef, 0xdf, 0xe2, 0xe3, 0xa7, + 0x5e, 0x54, 0xf7, 0x0e, 0xa0, 0xa6, 0x8f, 0x85, 0x89, 0x08, 0xd1, 0x48, + 0x01, 0x3d, 0xee, 0x7d, 0xd1, 0xd7, 0x42, 0xb4, 0x3a, 0xff, 0xce, 0x2d, + 0xce, 0x35, 0xdd, 0xa6, 0x88, 0x46, 0xe9, 0x4e, 0x75, 0x42, 0x26, 0x3f, + 0x1e, 0x00, 0xde, 0xc4, 0x8b, 0xff, 0xff, 0xdd, 0xc0, 0x71, 0x4e, 0xa6, + 0xf1, 0xe0, 0x74, 0x73, 0x7f, 0x01, 0xf4, 0x75, 0xff, 0xd9, 0xbf, 0xdf, + 0x20, 0x82, 0x59, 0xa3, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x33, + 0x8b, 0x86, 0x06, 0x78, 0xe0, 0x70, 0x73, 0xda, 0x46, 0xe0, 0xfd, 0x9f, + 0x39, 0x1a, 0x17, 0x53, 0x58, 0x9f, 0xfe, 0x0f, 0xc5, 0xc3, 0x03, 0x3c, + 0x70, 0xea, 0x84, 0xd3, 0xf1, 0x16, 0xff, 0xef, 0x38, 0xcf, 0xbc, 0x86, + 0x33, 0x47, 0x5f, 0xfb, 0xee, 0x75, 0xd6, 0xc3, 0x2c, 0xb2, 0x75, 0xff, + 0xfb, 0x1b, 0xd8, 0x10, 0x8a, 0x4f, 0x82, 0x8a, 0x1d, 0x73, 0xbc, 0xe8, + 0x96, 0x92, 0x25, 0xff, 0xfd, 0x30, 0xc7, 0xfa, 0x6f, 0x53, 0x93, 0x0c, + 0x7f, 0xa3, 0xaf, 0xfe, 0xf7, 0x53, 0x67, 0x5e, 0x5c, 0x85, 0x0e, 0xbf, + 0x81, 0xe4, 0x00, 0xa8, 0x75, 0xfd, 0x8c, 0xe0, 0x83, 0xf3, 0xaf, 0xd2, + 0xcf, 0x47, 0xe7, 0x5d, 0x0b, 0x9c, 0xf5, 0x37, 0x2d, 0xbf, 0xff, 0xfb, + 0xf5, 0xbc, 0xba, 0xe9, 0xe4, 0x0e, 0x07, 0x3c, 0x8b, 0x4e, 0x1d, 0x5a, + 0x44, 0xf0, 0x0b, 0xef, 0xd3, 0xae, 0x03, 0x07, 0x54, 0x97, 0x3f, 0x43, + 0x1e, 0x46, 0xe4, 0x53, 0x43, 0x67, 0x85, 0xdd, 0x5d, 0xd2, 0x37, 0xa3, + 0x1f, 0xfa, 0x47, 0x7f, 0xa3, 0x5a, 0x89, 0xf1, 0x93, 0xaf, 0xf7, 0x71, + 0x79, 0xd0, 0x09, 0xd4, 0x13, 0xe4, 0xf1, 0x9d, 0x62, 0x63, 0x8f, 0x0f, + 0xab, 0xcc, 0xb2, 0xc9, 0x57, 0xfd, 0x9f, 0xbf, 0x33, 0x66, 0x04, 0xa6, + 0x0b, 0xfb, 0x99, 0x64, 0xab, 0xcc, 0xb2, 0xc9, 0x57, 0xf3, 0xce, 0x1e, + 0xc6, 0x8a, 0x60, 0xbf, 0xa1, 0x45, 0xeb, 0x29, 0x3b, 0x66, 0xf7, 0xe6, + 0xa0, 0x7e, 0xac, 0xa6, 0x0d, 0x9d, 0xe6, 0x59, 0x64, 0xab, 0xda, 0x8e, + 0x14, 0xc1, 0x7f, 0x7c, 0xe3, 0xbf, 0x8e, 0xb7, 0xe8, 0x8a, 0x5f, 0x2c, + 0xb2, 0x57, 0x7f, 0x04, 0x62, 0x4e, 0xd3, 0xaf, 0xda, 0x04, 0xfb, 0x62, + 0x75, 0xf8, 0x29, 0xb2, 0x02, 0x75, 0xf6, 0x0e, 0x2b, 0x9d, 0x5c, 0x3c, + 0xa5, 0x94, 0x52, 0x22, 0x5f, 0xeb, 0xad, 0xff, 0xdd, 0x79, 0x0b, 0xa9, + 0x30, 0xa4, 0xc7, 0x5f, 0xfd, 0x9c, 0x9e, 0x37, 0xd2, 0x0e, 0x7e, 0x75, + 0xfd, 0xdc, 0xd9, 0x9e, 0xd1, 0xd4, 0xd4, 0x5b, 0x7e, 0x89, 0xe4, 0x4a, + 0xe2, 0x79, 0xbd, 0x86, 0x10, 0xc3, 0x6a, 0xe9, 0xfc, 0x75, 0x42, 0xa5, + 0x5c, 0x94, 0x08, 0x27, 0x57, 0xb7, 0x56, 0xaa, 0xc1, 0xd7, 0xff, 0xb1, + 0x5d, 0xc7, 0xfc, 0x6c, 0x76, 0x16, 0x75, 0xf6, 0xba, 0x93, 0x15, 0x7f, + 0xcf, 0xbf, 0xb2, 0x60, 0x71, 0x43, 0xac, 0xd4, 0x3d, 0xd0, 0x11, 0x5f, + 0xe1, 0xcd, 0xe5, 0xa4, 0x50, 0xeb, 0xe7, 0x7e, 0x28, 0x75, 0x7c, 0x3d, + 0x49, 0xcc, 0xef, 0xfb, 0x31, 0xbf, 0xc6, 0x6f, 0x23, 0xaf, 0xa1, 0xd7, + 0xb0, 0xab, 0xff, 0xba, 0x8f, 0xff, 0xf1, 0xfc, 0x77, 0x47, 0x5f, 0xdd, + 0xc5, 0xad, 0xe4, 0x75, 0xe6, 0x59, 0x64, 0xab, 0xfc, 0x3e, 0xea, 0x40, + 0xce, 0x53, 0x05, 0xfd, 0xe8, 0xff, 0x24, 0x88, 0xcc, 0x4b, 0xaf, 0x26, + 0x09, 0xf6, 0x1a, 0x36, 0xc6, 0xa6, 0xa2, 0xb8, 0xc9, 0xaf, 0xf4, 0x7d, + 0xe7, 0x13, 0xda, 0x3a, 0xa1, 0x5a, 0xdc, 0x8a, 0x37, 0x85, 0x3a, 0x3d, + 0xcc, 0x4b, 0xd8, 0xe2, 0x44, 0xbe, 0xfd, 0xfe, 0x27, 0x54, 0x3a, 0xff, + 0xfb, 0x1b, 0x02, 0xfe, 0xd0, 0x40, 0xfc, 0x91, 0xd5, 0xb9, 0xfa, 0xac, + 0xa2, 0xf3, 0x63, 0x47, 0x5f, 0xfd, 0xf6, 0x59, 0xd7, 0xea, 0x73, 0x90, + 0x75, 0x61, 0xef, 0xfe, 0x37, 0x7e, 0x8f, 0x6b, 0x66, 0x1d, 0x7e, 0x07, + 0x14, 0xea, 0x1d, 0x50, 0x8f, 0x41, 0x84, 0x17, 0x88, 0xb6, 0xca, 0x2f, + 0xff, 0x93, 0x66, 0x08, 0x45, 0xd9, 0xc1, 0x75, 0x0e, 0xbf, 0xff, 0xe0, + 0xf5, 0x19, 0xcd, 0xa4, 0x5b, 0xfb, 0x40, 0x96, 0x6f, 0xe3, 0xab, 0x11, + 0x70, 0xe9, 0xd7, 0xfd, 0x33, 0x7a, 0x8b, 0x8e, 0x28, 0x75, 0xfa, 0x7f, + 0x80, 0x89, 0x8e, 0xb4, 0x8e, 0xbd, 0xf4, 0x66, 0x3a, 0xa4, 0x6b, 0xbf, + 0x10, 0xac, 0x45, 0xab, 0x9d, 0x69, 0x66, 0xa1, 0xd9, 0xbc, 0x4f, 0x28, + 0xf6, 0x52, 0x91, 0x43, 0x2a, 0x97, 0x29, 0x48, 0xca, 0x42, 0xd9, 0xa7, + 0x69, 0x29, 0x5a, 0x69, 0x50, 0x9c, 0x94, 0x90, 0xb9, 0x44, 0xbd, 0x96, + 0xbc, 0xf1, 0xcf, 0xff, 0x0e, 0x51, 0x9e, 0x58, 0xd4, 0xe1, 0x87, 0xa5, + 0xc8, 0x82, 0x3d, 0x96, 0x61, 0xf7, 0xf6, 0x1a, 0xd7, 0xb6, 0x40, 0x9d, + 0x7f, 0xfd, 0x82, 0xc7, 0x94, 0x4d, 0xf5, 0xdc, 0xfd, 0xce, 0xa9, 0x1f, + 0x68, 0x47, 0x2f, 0xf3, 0x8b, 0x73, 0xdd, 0x43, 0xab, 0x73, 0xd2, 0x59, + 0x15, 0x95, 0xa1, 0xd7, 0xfe, 0x71, 0xff, 0xe0, 0x40, 0xfc, 0x91, 0xd7, + 0xc8, 0x33, 0xc1, 0xd4, 0xae, 0x7c, 0x1c, 0x40, 0xa5, 0x5e, 0x89, 0xbc, + 0x76, 0xbd, 0x03, 0x39, 0xd7, 0xc9, 0xd4, 0x59, 0xd6, 0xea, 0x1b, 0xb9, + 0x86, 0xef, 0xe8, 0x6c, 0x6b, 0xc8, 0x75, 0xff, 0x47, 0xba, 0xff, 0xbe, + 0xfa, 0x3a, 0x82, 0x7c, 0x82, 0x57, 0x7f, 0xee, 0x7f, 0xf3, 0xa8, 0xd0, + 0x73, 0xf3, 0xaf, 0x4c, 0x0e, 0x1d, 0x7f, 0xe7, 0x4e, 0x66, 0xec, 0x32, + 0xcb, 0x27, 0x54, 0x22, 0x89, 0xd0, 0xf4, 0x3b, 0x7f, 0xfc, 0x31, 0x2f, + 0x9f, 0x7c, 0x82, 0x09, 0x66, 0x8e, 0xac, 0x4f, 0x35, 0xb0, 0x8b, 0xec, + 0x30, 0xff, 0x2e, 0xbf, 0xd0, 0x32, 0x1c, 0xcf, 0xce, 0xbf, 0xb3, 0x9a, + 0x18, 0x9c, 0xeb, 0xf9, 0xfd, 0xd7, 0x1f, 0xce, 0xbf, 0xf3, 0xfb, 0x26, + 0x78, 0x18, 0x98, 0xeb, 0x27, 0x0f, 0xa3, 0xa5, 0x97, 0x35, 0xa6, 0x8c, + 0x12, 0xa4, 0x8d, 0xe6, 0xc2, 0x53, 0xf2, 0x7b, 0xb0, 0x4e, 0xbf, 0xfd, + 0xe8, 0x16, 0xe7, 0xba, 0x9c, 0xfd, 0xa7, 0x50, 0x4f, 0x77, 0x05, 0x2f, + 0xf4, 0x2f, 0x5a, 0x71, 0x9c, 0xeb, 0xed, 0x60, 0xf8, 0xeb, 0xdb, 0x51, + 0xc3, 0xa9, 0xcd, 0xf0, 0x08, 0x2f, 0x79, 0xd5, 0xce, 0xbf, 0xde, 0xea, + 0x31, 0xfb, 0xa1, 0xd4, 0x14, 0xc0, 0xba, 0x42, 0x2e, 0x1e, 0x20, 0x00, + 0xf5, 0xf7, 0x51, 0xe4, 0x75, 0xe0, 0xbc, 0x8e, 0xb8, 0x1f, 0xc1, 0xbb, + 0xc2, 0x0b, 0xfe, 0x6e, 0x7a, 0x36, 0x20, 0xfe, 0x75, 0xff, 0xfc, 0x08, + 0xf6, 0xb0, 0x7e, 0x72, 0x10, 0x22, 0xf2, 0x3a, 0xfc, 0xde, 0xee, 0xea, + 0xe7, 0x5f, 0xfc, 0x81, 0x10, 0x7b, 0x50, 0x31, 0xa3, 0xa9, 0x11, 0xfc, + 0x27, 0x20, 0x59, 0xd8, 0x57, 0x7f, 0xf7, 0xef, 0xcc, 0xd9, 0x81, 0xe0, + 0xb2, 0x75, 0xff, 0xfc, 0x39, 0xa0, 0x7c, 0xce, 0xb8, 0xe4, 0xd2, 0x8d, + 0xce, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x40, 0xd7, 0xf3, 0xcf, 0xfb, 0x88, + 0x49, 0x58, 0x3e, 0xf6, 0x68, 0x18, 0x7d, 0xdb, 0x66, 0x77, 0xba, 0xf2, + 0xf8, 0x8f, 0xe1, 0x86, 0x4d, 0x2d, 0x37, 0xef, 0x46, 0x89, 0x7f, 0xc3, + 0xff, 0x92, 0x75, 0xc3, 0x4e, 0xbf, 0x05, 0x5b, 0x70, 0xab, 0x67, 0x54, + 0x2a, 0x4f, 0xc8, 0xee, 0xd0, 0xa9, 0xce, 0x6f, 0xf6, 0x6f, 0xe0, 0xe6, + 0x28, 0x75, 0xfd, 0x9e, 0x81, 0x4f, 0xce, 0xbc, 0xfc, 0x9c, 0xd1, 0x82, + 0xdf, 0xf9, 0xf9, 0x83, 0xfe, 0xbd, 0xad, 0xce, 0xbf, 0xff, 0xff, 0xb3, + 0xdd, 0x71, 0x53, 0xe6, 0xb8, 0xef, 0xed, 0x98, 0x1f, 0x98, 0xb7, 0x1d, + 0xe4, 0x78, 0x82, 0xef, 0xfc, 0xee, 0xa3, 0x5c, 0x3f, 0x14, 0x64, 0xf1, + 0x05, 0xdf, 0xfd, 0xd4, 0xea, 0x40, 0xfb, 0xe2, 0x8c, 0x9e, 0x20, 0xbb, + 0xfd, 0x08, 0x3e, 0xf8, 0xa3, 0x27, 0x88, 0x2e, 0xfe, 0x5e, 0x07, 0xe2, + 0x8c, 0x9e, 0x20, 0xbb, 0xff, 0xfe, 0x71, 0x14, 0x5f, 0xcd, 0x37, 0xa9, + 0xc4, 0x52, 0x7c, 0x64, 0xf1, 0x05, 0xdd, 0xbf, 0xc0, 0xa7, 0x2e, 0xd4, + 0xfe, 0x29, 0xba, 0x10, 0x9f, 0x54, 0x2a, 0xc8, 0xe9, 0xf8, 0xca, 0x31, + 0xbf, 0xc9, 0x0a, 0x6b, 0xda, 0xdc, 0xeb, 0xe7, 0xe7, 0xee, 0x75, 0xff, + 0xdd, 0x4e, 0xa4, 0x0f, 0xbe, 0x28, 0xc9, 0xe2, 0x0b, 0xbf, 0xe9, 0xb4, + 0xd4, 0x9f, 0xe2, 0x8c, 0x9e, 0x20, 0xbb, 0xf7, 0xb5, 0x0b, 0xf8, 0xd4, + 0x4f, 0xfd, 0x53, 0xbf, 0xfd, 0xf1, 0xbd, 0x46, 0xc7, 0xb5, 0xf1, 0x46, + 0x4f, 0x10, 0x5d, 0xff, 0xff, 0xc2, 0x28, 0xbf, 0x80, 0xcf, 0x9a, 0x6f, + 0x53, 0x88, 0xa4, 0xf8, 0xc9, 0xe2, 0x0b, 0xac, 0x4c, 0x93, 0x74, 0x47, + 0x5d, 0xbf, 0xee, 0xa7, 0x11, 0x49, 0xf1, 0x93, 0xc4, 0x17, 0x7f, 0xfc, + 0xef, 0xbc, 0xb5, 0xd4, 0x08, 0x63, 0x90, 0x55, 0xff, 0xb2, 0x52, 0x06, + 0xb8, 0x33, 0xed, 0x9e, 0x20, 0xba, 0x6a, 0x39, 0x38, 0x8f, 0xa4, 0xeb, + 0xff, 0x35, 0x39, 0xe7, 0xff, 0x5f, 0x19, 0x3c, 0x41, 0x77, 0xf7, 0x53, + 0xbd, 0x4f, 0xcd, 0x00, 0x5d, 0xfb, 0x3f, 0xf8, 0xa3, 0x27, 0x88, 0x2e, + 0xec, 0xf3, 0x4f, 0xcf, 0xa7, 0x55, 0xba, 0x3b, 0xf5, 0x0c, 0x2b, 0xf9, + 0x78, 0x1f, 0x8a, 0x32, 0x78, 0x82, 0xef, 0xfc, 0xde, 0xa7, 0x11, 0x49, + 0xf1, 0x93, 0xc4, 0x17, 0x76, 0x7c, 0x74, 0x45, 0xe8, 0xfa, 0xff, 0x01, + 0x16, 0xe3, 0xbc, 0x8f, 0x10, 0x5d, 0xff, 0xb1, 0x36, 0x60, 0xe0, 0x5e, + 0x47, 0x88, 0x2d, 0x66, 0xfe, 0x82, 0xbb, 0xfb, 0xc3, 0x7f, 0xcd, 0x06, + 0x3e, 0x4d, 0x46, 0x29, 0xe8, 0xc7, 0xc1, 0x0b, 0x46, 0x5b, 0xae, 0xfe, + 0x0d, 0x10, 0x5b, 0x08, 0x8c, 0xb9, 0xda, 0x75, 0xb4, 0xd6, 0x4e, 0x2f, + 0xf4, 0x97, 0xaf, 0x1b, 0x5d, 0x2d, 0xa3, 0xaf, 0x44, 0xb6, 0x8e, 0xa8, + 0x36, 0xe2, 0x33, 0x53, 0xb2, 0xaf, 0x42, 0x67, 0xfd, 0x27, 0xc0, 0x5e, + 0xef, 0xfe, 0xc9, 0x0e, 0x7b, 0xa9, 0x9b, 0xf8, 0xeb, 0xf4, 0x7b, 0x5d, + 0x43, 0xaf, 0xfd, 0xa9, 0xa4, 0x00, 0xcd, 0x20, 0x04, 0xea, 0x91, 0xf4, + 0x78, 0x9a, 0xff, 0xe8, 0xde, 0x5f, 0x57, 0xaf, 0x46, 0xec, 0x9d, 0x7e, + 0x96, 0xd6, 0xd0, 0x27, 0x3a, 0xdd, 0x43, 0xf8, 0x74, 0x9b, 0xf7, 0x23, + 0x79, 0x68, 0xea, 0x91, 0xe7, 0x70, 0x9a, 0xff, 0xef, 0xc1, 0xad, 0xbc, + 0xe7, 0xeb, 0x4d, 0x1d, 0x7f, 0xbf, 0x07, 0x86, 0x3d, 0xa3, 0xab, 0xf3, + 0xfc, 0xd2, 0x4d, 0x42, 0x75, 0x39, 0x0e, 0x87, 0x84, 0xf5, 0xfc, 0xf2, + 0x8d, 0x8f, 0xd3, 0xaf, 0xb7, 0xd4, 0x6e, 0x75, 0xe5, 0xc4, 0x8e, 0xbf, + 0x60, 0x7a, 0x06, 0x4e, 0xaf, 0x87, 0xcc, 0xe4, 0x62, 0x37, 0x78, 0x2f, + 0xe3, 0xab, 0x87, 0x94, 0xe5, 0xf7, 0x93, 0x6f, 0x0e, 0xbc, 0xfc, 0xfc, + 0xeb, 0x6f, 0x06, 0xe7, 0xc3, 0xb7, 0xcc, 0xe7, 0x5c, 0xeb, 0xe5, 0x38, + 0x8c, 0x9d, 0x7e, 0x9d, 0xfb, 0x0a, 0xe7, 0x52, 0xb0, 0x79, 0xb8, 0x47, + 0x50, 0x9f, 0x92, 0x43, 0x75, 0xd6, 0xbf, 0x27, 0x16, 0xeb, 0xff, 0xc2, + 0x31, 0x3a, 0xfa, 0x9c, 0xe3, 0xc8, 0xeb, 0xfd, 0x3c, 0xf0, 0x3b, 0xe7, + 0x8e, 0xac, 0x3f, 0xc4, 0x48, 0xbf, 0xfb, 0x82, 0x0d, 0xfc, 0x39, 0x3b, + 0x89, 0xd7, 0x9f, 0x93, 0x9d, 0x77, 0xf0, 0x75, 0xf2, 0x42, 0xf0, 0xea, + 0x3a, 0xfe, 0x75, 0x3d, 0x1c, 0xfc, 0xea, 0x09, 0xb8, 0x10, 0xab, 0xff, + 0xfd, 0x08, 0x11, 0x80, 0x37, 0xd8, 0xd0, 0xc3, 0x7e, 0xac, 0xeb, 0xbf, + 0x83, 0xae, 0x85, 0x0e, 0xbf, 0xec, 0xf6, 0xa1, 0x7f, 0x72, 0x63, 0xaf, + 0xf6, 0xb3, 0xa9, 0xa0, 0x4e, 0x75, 0xcc, 0xb2, 0x55, 0xff, 0x0e, 0x6c, + 0x79, 0x69, 0x02, 0x75, 0x35, 0x3f, 0x24, 0x1c, 0xe0, 0xb2, 0xd5, 0xfa, + 0x41, 0xfb, 0x02, 0xa4, 0x58, 0x45, 0xb4, 0x74, 0xc9, 0x9f, 0xd1, 0x8b, + 0xcc, 0xb2, 0xc9, 0x56, 0x59, 0x4c, 0x17, 0xf7, 0xd3, 0x3b, 0xf0, 0xa6, + 0x11, 0xbd, 0xf6, 0x17, 0xd5, 0x3a, 0xb5, 0xb7, 0x96, 0x27, 0x7f, 0x7a, + 0x33, 0xb9, 0x39, 0xd7, 0x62, 0xce, 0xad, 0xcf, 0x07, 0x45, 0x95, 0x0d, + 0xf3, 0x8c, 0xa1, 0x7d, 0x92, 0x8c, 0x14, 0x48, 0xde, 0x30, 0xe4, 0x8e, + 0x57, 0x90, 0x85, 0xec, 0xb7, 0x97, 0xa5, 0x7f, 0x7e, 0x96, 0x32, 0x94, + 0xf5, 0x28, 0xab, 0xd0, 0xc9, 0x04, 0xb7, 0xbd, 0x8d, 0xb7, 0xf6, 0x7f, + 0xfa, 0x72, 0x47, 0x5c, 0xdc, 0x3a, 0x82, 0x78, 0x6e, 0x5d, 0x76, 0x32, + 0x75, 0xd1, 0xe3, 0xaa, 0x73, 0x56, 0xd1, 0x6b, 0x2c, 0xea, 0xc3, 0x65, + 0xe2, 0x2b, 0xfd, 0x24, 0x1c, 0x58, 0x3a, 0x75, 0xff, 0xb3, 0xda, 0xea, + 0x2d, 0xf3, 0x87, 0x54, 0x1f, 0x68, 0x98, 0xdf, 0x7c, 0xf4, 0x6c, 0x3a, + 0xfb, 0x17, 0x9e, 0x3a, 0xf7, 0x9d, 0x43, 0xaf, 0xff, 0xfe, 0x6b, 0xcc, + 0x09, 0x01, 0xbf, 0x3a, 0x9e, 0xf4, 0x6f, 0x13, 0xc6, 0x8e, 0xbf, 0xff, + 0xe5, 0x71, 0x77, 0xd9, 0x12, 0xec, 0x72, 0x78, 0xf6, 0x9e, 0x47, 0x5e, + 0x4d, 0xe6, 0x3a, 0xfd, 0x99, 0x38, 0x34, 0x75, 0xf7, 0x05, 0x3f, 0x3a, + 0xf9, 0x1a, 0xfc, 0x3a, 0xe8, 0xfc, 0xeb, 0xe0, 0x4e, 0x06, 0x3a, 0x6d, + 0xbe, 0x90, 0x52, 0x22, 0x53, 0xaa, 0xf7, 0xfd, 0xd7, 0xd7, 0x52, 0x77, + 0x13, 0xaf, 0x9e, 0x7f, 0xb2, 0x3a, 0x95, 0x4a, 0xf0, 0x21, 0xfa, 0x50, + 0x8d, 0xc2, 0x0d, 0xc9, 0x50, 0x83, 0x83, 0x8e, 0xed, 0xfb, 0x4e, 0x87, + 0x7d, 0x0b, 0xbf, 0xa4, 0x5b, 0x46, 0xf7, 0xf0, 0x80, 0x2b, 0x79, 0x1d, + 0x79, 0x27, 0x01, 0xd7, 0xe8, 0xfd, 0x37, 0xc3, 0xae, 0x5e, 0xc3, 0xac, + 0x18, 0x37, 0xe2, 0x4f, 0x7f, 0xfa, 0x43, 0x1f, 0x16, 0x30, 0xa7, 0x92, + 0x73, 0xaf, 0xce, 0xbc, 0xea, 0xce, 0xad, 0xcf, 0xc7, 0xc9, 0x77, 0xbd, + 0xc8, 0x3a, 0xff, 0x6b, 0xdb, 0x30, 0x70, 0x27, 0x54, 0x27, 0x1d, 0x22, + 0xcc, 0x5b, 0x48, 0x4b, 0x2c, 0x8d, 0xc6, 0xef, 0x3f, 0xcf, 0xa7, 0x5f, + 0x2d, 0x70, 0xb3, 0xaf, 0xff, 0x86, 0x5f, 0x30, 0x29, 0xad, 0xfc, 0x07, + 0xd1, 0xd7, 0xfb, 0xe8, 0xbf, 0xa5, 0x0a, 0x1d, 0x7d, 0x99, 0xbc, 0x8e, + 0xbd, 0xa4, 0x98, 0xeb, 0x28, 0x26, 0xf7, 0x44, 0x37, 0xff, 0x3c, 0xe3, + 0x1b, 0xa0, 0x46, 0x27, 0x3a, 0xb8, 0x7d, 0x42, 0x4f, 0x7e, 0xf9, 0xd8, + 0xe4, 0x8e, 0xaf, 0x89, 0xdb, 0x40, 0xfe, 0x10, 0xb5, 0x45, 0xe1, 0xb6, + 0xc9, 0x0d, 0xe5, 0xea, 0x0e, 0xbf, 0xa7, 0x9a, 0x4a, 0xae, 0x4e, 0x75, + 0xf2, 0xf1, 0xfa, 0x75, 0xd2, 0x9c, 0xeb, 0xdd, 0x0a, 0x1d, 0x7e, 0xee, + 0x24, 0xb4, 0x75, 0xff, 0xf7, 0x63, 0xeb, 0x1e, 0x17, 0xff, 0x5a, 0x8f, + 0xca, 0xbf, 0x71, 0xae, 0xed, 0x3c, 0x40, 0x97, 0xb5, 0x1b, 0x9d, 0x6f, + 0xf0, 0xf3, 0xf7, 0x33, 0xbd, 0xe4, 0x9c, 0xeb, 0xd3, 0xb8, 0x9d, 0x52, + 0x4c, 0xa0, 0x24, 0xdc, 0x85, 0x12, 0xca, 0x7c, 0x39, 0x7f, 0x0b, 0x5d, + 0x4e, 0xa1, 0xd7, 0x6d, 0x48, 0xeb, 0xef, 0x4e, 0xe2, 0x75, 0xe1, 0x75, + 0x0e, 0xbc, 0xa2, 0x78, 0xeb, 0xda, 0x7f, 0x1d, 0x4a, 0x1b, 0x7d, 0xc7, + 0x2e, 0xf9, 0xd3, 0xaf, 0xe5, 0xf9, 0x02, 0x08, 0x3a, 0xf2, 0xfc, 0xd3, + 0xad, 0xe8, 0x3c, 0x8c, 0x2c, 0xa9, 0xd3, 0x35, 0xc1, 0x96, 0x90, 0xf5, + 0x4b, 0xf2, 0x31, 0x60, 0xbb, 0x80, 0x3a, 0xff, 0x0b, 0xb3, 0xad, 0x47, + 0xe7, 0x5e, 0xdb, 0x75, 0x0e, 0xbf, 0xe8, 0x5c, 0xb2, 0x7c, 0x02, 0xa4, + 0xeb, 0xe7, 0xf2, 0xa6, 0x73, 0xab, 0x11, 0x02, 0x83, 0xee, 0x79, 0x79, + 0x96, 0x59, 0x3d, 0x5f, 0x57, 0x9c, 0x42, 0x5a, 0xbe, 0xac, 0x1a, 0xcb, + 0xf6, 0x48, 0x10, 0xa1, 0xd5, 0x09, 0xc1, 0x84, 0x5b, 0x90, 0xb4, 0xfd, + 0x67, 0xc7, 0x37, 0xff, 0xec, 0x14, 0x51, 0x8d, 0x7b, 0xa0, 0x79, 0x4a, + 0x0e, 0xa9, 0xd1, 0x4a, 0xa2, 0x85, 0xf6, 0x05, 0xe4, 0x75, 0xf9, 0xc4, + 0x51, 0x67, 0x5f, 0xf7, 0x53, 0x98, 0x8b, 0x85, 0x73, 0xaf, 0xc8, 0xb7, + 0x1c, 0x3a, 0xbe, 0x2f, 0x60, 0xab, 0x23, 0x70, 0x6b, 0x22, 0x00, 0x8b, + 0xe4, 0x68, 0x6a, 0x28, 0x24, 0x6c, 0x2f, 0x2a, 0x03, 0xf2, 0x51, 0x20, + 0x01, 0x26, 0xd9, 0xcd, 0xf9, 0x3d, 0x1e, 0xd1, 0x57, 0xcd, 0x8f, 0x68, + 0xab, 0x99, 0x64, 0xaa, 0x91, 0xef, 0xe1, 0x33, 0x24, 0x37, 0x63, 0x25, + 0x30, 0x6b, 0xef, 0xff, 0xbd, 0x0d, 0xcc, 0x1f, 0x75, 0x20, 0x67, 0x3a, + 0x8e, 0xac, 0x3d, 0x6d, 0x26, 0x57, 0xe8, 0x9e, 0x65, 0xf6, 0xff, 0xff, + 0x46, 0xc4, 0x1f, 0xfe, 0x7b, 0x58, 0xde, 0xb8, 0xfb, 0x47, 0x5f, 0xa5, + 0xd0, 0x47, 0x0e, 0xbf, 0xf9, 0xd7, 0xc8, 0xd8, 0x9b, 0x04, 0x1a, 0x3a, + 0xb7, 0x3e, 0xde, 0x93, 0xdf, 0xb0, 0x0b, 0x8d, 0x1d, 0x47, 0x5d, 0x93, + 0x70, 0xd8, 0x68, 0x9a, 0xff, 0x90, 0x0a, 0x9e, 0xc7, 0xd1, 0x9c, 0xeb, + 0xfe, 0x89, 0xe3, 0x7f, 0x0e, 0x4e, 0x75, 0x62, 0x29, 0x1a, 0x5a, 0x87, + 0xd7, 0xe7, 0x58, 0xc6, 0xe7, 0x54, 0xc9, 0xa5, 0xf2, 0x1e, 0xfd, 0x2e, + 0xbe, 0xce, 0xe4, 0xe7, 0x5e, 0x93, 0xf0, 0xeb, 0xf4, 0xb3, 0xd8, 0x12, + 0xaf, 0xa0, 0x46, 0x0e, 0xa9, 0x8f, 0x7f, 0xc3, 0x7f, 0x49, 0xaf, 0xbf, + 0xd2, 0xf8, 0x75, 0x28, 0x8d, 0x54, 0x84, 0x07, 0x8c, 0xaf, 0xf8, 0x73, + 0xb9, 0xf3, 0xb9, 0x39, 0xd7, 0xf0, 0x15, 0x29, 0xce, 0x61, 0xd7, 0xde, + 0x53, 0x3a, 0x75, 0xb4, 0x75, 0xc9, 0xf9, 0xd7, 0x75, 0x0e, 0xb8, 0x1a, + 0xf8, 0x6a, 0xe6, 0x16, 0xa7, 0x3e, 0xbf, 0xce, 0xee, 0xfe, 0x0e, 0xbb, + 0xf8, 0x3a, 0xfc, 0x09, 0x60, 0xb0, 0x86, 0xb3, 0xf1, 0x6a, 0x84, 0xc6, + 0x7f, 0x84, 0x68, 0xa7, 0x5f, 0xff, 0x60, 0xbe, 0xfa, 0x51, 0x47, 0xf8, + 0xd5, 0xfe, 0x75, 0xff, 0xde, 0xee, 0x2f, 0xec, 0x7f, 0x9b, 0xf8, 0xeb, + 0xfd, 0xbb, 0x53, 0x9f, 0x60, 0x27, 0x5f, 0x7e, 0xb7, 0x97, 0xc4, 0x68, + 0x69, 0x53, 0xc8, 0xf7, 0xf7, 0xeb, 0xfb, 0xaf, 0xb3, 0x9d, 0x76, 0x6e, + 0x75, 0x6e, 0x79, 0x5b, 0x66, 0x97, 0xdf, 0xf1, 0x38, 0x75, 0x42, 0x37, + 0x1e, 0x12, 0x8c, 0x93, 0x5f, 0x68, 0x1b, 0xf8, 0xeb, 0xb1, 0x93, 0xaf, + 0xfa, 0x37, 0xcf, 0xe3, 0x66, 0x4e, 0x75, 0x70, 0xf4, 0x7f, 0x16, 0xbf, + 0xf4, 0xd1, 0x3e, 0xb9, 0x8d, 0x89, 0xce, 0xbf, 0xb1, 0x78, 0x14, 0x64, + 0xeb, 0x97, 0x07, 0x52, 0xcf, 0x05, 0xcb, 0x2f, 0xe1, 0xc9, 0xba, 0x9e, + 0x3a, 0xfb, 0x33, 0xba, 0x3a, 0xb1, 0x1d, 0xcf, 0x08, 0x1f, 0x10, 0xed, + 0x16, 0x5e, 0x65, 0x96, 0x4a, 0xbf, 0x62, 0x82, 0x0d, 0x14, 0xc1, 0x7f, + 0x7e, 0xc6, 0x19, 0x65, 0x93, 0xaa, 0x0f, 0x8b, 0xc6, 0xf7, 0xfd, 0xae, + 0x40, 0x3c, 0x29, 0xb0, 0xeb, 0xff, 0x0e, 0x69, 0xbd, 0x46, 0xc0, 0x9d, + 0x7f, 0xff, 0x94, 0x65, 0xf8, 0xa3, 0x1a, 0xc9, 0x08, 0x1f, 0x58, 0x27, + 0x54, 0x23, 0x5b, 0x0e, 0x50, 0xee, 0xf9, 0x97, 0x19, 0x1d, 0x7f, 0xde, + 0x8d, 0xff, 0x7e, 0xf5, 0x0e, 0xb7, 0x4e, 0xac, 0x3c, 0x96, 0x9c, 0xde, + 0x65, 0x96, 0x4a, 0xbf, 0x91, 0xd4, 0xea, 0x78, 0xa6, 0x0b, 0xfb, 0xef, + 0x69, 0xf8, 0x75, 0xee, 0xc0, 0x4e, 0xa4, 0x37, 0x8e, 0x43, 0x7e, 0xcf, + 0xf3, 0x26, 0x3a, 0xda, 0xf8, 0x8f, 0xee, 0x20, 0x75, 0xe0, 0x47, 0xee, + 0x04, 0x82, 0x9d, 0x66, 0x46, 0xd1, 0x7e, 0x54, 0xf6, 0x27, 0x01, 0xd5, + 0xd5, 0x47, 0x43, 0x1e, 0xc8, 0x0d, 0x6f, 0x46, 0xc8, 0x3a, 0x90, 0xf4, + 0xc4, 0xde, 0xf0, 0xc6, 0xc3, 0xae, 0x54, 0xa1, 0xd7, 0x27, 0x4e, 0xb3, + 0xce, 0x6b, 0xb8, 0x33, 0x7d, 0xed, 0x01, 0x5c, 0xeb, 0xfd, 0x03, 0x21, + 0x48, 0xdc, 0xea, 0x86, 0x6e, 0x5c, 0x89, 0x72, 0x50, 0xda, 0x91, 0x86, + 0x34, 0xd5, 0x0e, 0x79, 0x1a, 0x4f, 0x63, 0xe1, 0x73, 0x4f, 0xdd, 0x06, + 0x31, 0x1d, 0x43, 0x13, 0xd2, 0xe1, 0x36, 0x10, 0x6d, 0xa5, 0x7d, 0x27, + 0xda, 0x25, 0xb9, 0x58, 0x43, 0xaf, 0xfd, 0x13, 0x7b, 0x6b, 0x51, 0x30, + 0x38, 0x75, 0xff, 0xd8, 0x9d, 0x80, 0xf4, 0x11, 0xbe, 0x8e, 0xbc, 0x15, + 0x3f, 0x3a, 0xfc, 0xbe, 0x71, 0xfc, 0x75, 0x7c, 0x3c, 0x58, 0x1e, 0xbf, + 0xfc, 0xd9, 0x9d, 0xbd, 0x89, 0x78, 0x71, 0x67, 0x5f, 0xff, 0x22, 0xf7, + 0x96, 0xbe, 0x60, 0x8e, 0x27, 0xe7, 0x5e, 0x4e, 0x80, 0xea, 0x56, 0x53, + 0xbc, 0x90, 0xd7, 0x10, 0xfb, 0x08, 0x87, 0x23, 0xf2, 0x4e, 0xc5, 0x0b, + 0x30, 0xac, 0x46, 0xc5, 0xf8, 0xa8, 0x85, 0xca, 0xb7, 0x1a, 0x42, 0xa9, + 0xb1, 0x5a, 0x46, 0x32, 0xab, 0xe3, 0x16, 0x56, 0xa7, 0x4a, 0xb0, 0x7c, + 0x53, 0x00, 0x27, 0x9d, 0x08, 0x95, 0x22, 0x4c, 0x34, 0x90, 0xcc, 0xb6, + 0x8e, 0x8a, 0x4b, 0x0e, 0x6d, 0x26, 0x23, 0x79, 0xf5, 0xf4, 0xa4, 0x67, + 0x4d, 0x4e, 0x08, 0xe5, 0x34, 0xa5, 0x73, 0xf1, 0x1d, 0xad, 0x9e, 0x9e, + 0xb9, 0xce, 0xfe, 0x92, 0x60, 0xa9, 0x86, 0xb0, 0xd6, 0x69, 0xfa, 0xb6, + 0xaf, 0xbe, 0xb4, 0x17, 0xa0, 0x9d, 0x1b, 0xd9, 0x29, 0x4d, 0x99, 0x41, + 0xfb, 0x73, 0xe3, 0xdf, 0x69, 0xf8, 0xdb, 0x52, 0xb6, 0x29, 0x88, 0xd9, + 0x8e, 0xa5, 0x9b, 0x1a, 0x65, 0xf9, 0x8f, 0xd7, 0x9e, 0x3a, 0xff, 0x31, + 0x9c, 0x6b, 0xbb, 0x4d, 0x17, 0x1d, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, + 0x2e, 0xbb, 0xff, 0x98, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x8d, + 0x44, 0x6d, 0x6e, 0x32, 0x85, 0xd8, 0x4a, 0x54, 0x84, 0x7b, 0x4a, 0x12, + 0x3a, 0x15, 0x77, 0x17, 0xcd, 0x9a, 0x47, 0xf3, 0xbd, 0x14, 0xf8, 0xff, + 0x68, 0xfe, 0xff, 0xf3, 0x0b, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, + 0xd5, 0xff, 0x2a, 0xee, 0xa2, 0xbb, 0xc6, 0xfb, 0x47, 0x5f, 0xb8, 0xd7, + 0x76, 0x9a, 0x23, 0x7b, 0xff, 0x3c, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, + 0x7e, 0xfe, 0x8f, 0x7d, 0xeb, 0xf8, 0xeb, 0xfd, 0x9f, 0x78, 0xa7, 0x41, + 0xa3, 0xac, 0xc2, 0xb5, 0x4c, 0x97, 0x11, 0x16, 0x67, 0xd4, 0xa1, 0x2e, + 0xbf, 0xcc, 0x67, 0x1a, 0xee, 0xd3, 0x45, 0x57, 0x72, 0x6d, 0x1d, 0x7c, + 0x8b, 0x7d, 0x87, 0x52, 0x86, 0xeb, 0xc3, 0x17, 0x87, 0x69, 0x93, 0xaf, + 0xe7, 0xec, 0xc3, 0x01, 0x3a, 0xff, 0xef, 0x76, 0x34, 0x2e, 0x05, 0x4a, + 0x70, 0xeb, 0xd1, 0x2c, 0x3a, 0x82, 0x88, 0xcd, 0xcb, 0x26, 0x46, 0xbf, + 0xe5, 0x30, 0x73, 0x7f, 0x3a, 0xce, 0xb8, 0x28, 0x75, 0xfd, 0x9c, 0x6b, + 0xbb, 0x4d, 0x12, 0x05, 0x7c, 0x3c, 0xd6, 0x05, 0x6f, 0xda, 0x71, 0x7d, + 0xce, 0xb8, 0x10, 0x75, 0x48, 0xf8, 0x37, 0x25, 0xe1, 0x35, 0xfe, 0x94, + 0x72, 0x78, 0xe4, 0xe7, 0x5f, 0xee, 0x4e, 0xb8, 0x19, 0x68, 0xea, 0x83, + 0xe7, 0xc3, 0x4b, 0xec, 0x9d, 0xc2, 0x75, 0xff, 0xec, 0x9b, 0xae, 0xbf, + 0x76, 0x3c, 0x05, 0x9d, 0x53, 0xab, 0x06, 0x09, 0x16, 0x42, 0xad, 0x43, + 0x27, 0x87, 0x28, 0xc2, 0x5f, 0xc4, 0x1f, 0x48, 0x6f, 0xfe, 0x1c, 0x9d, + 0x8d, 0xb8, 0x11, 0xcf, 0x1d, 0x4c, 0x23, 0x23, 0x90, 0x83, 0xbf, 0xcc, + 0x67, 0x1a, 0xee, 0xd3, 0x45, 0x91, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, + 0x8b, 0x5e, 0xff, 0xf6, 0x7d, 0x89, 0xd8, 0xc9, 0xbc, 0x18, 0x13, 0xaf, + 0xf3, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x72, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, + 0x2e, 0xcb, 0xff, 0x3c, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8a, 0x3a, 0xcc, + 0x61, 0xfe, 0xac, 0xce, 0xf8, 0x62, 0x4b, 0x3a, 0xd2, 0x3a, 0xfd, 0xc6, + 0xbb, 0xb4, 0xd1, 0x4a, 0xdf, 0xf3, 0x7a, 0x93, 0x76, 0x27, 0xc3, 0xaf, + 0xff, 0x76, 0x27, 0x8e, 0xa6, 0xc7, 0x0f, 0x50, 0xe6, 0x0d, 0xcd, 0xd2, + 0x63, 0x11, 0x8f, 0x33, 0x65, 0x6e, 0x98, 0x3b, 0xc3, 0x5e, 0xff, 0xce, + 0x9e, 0x90, 0x02, 0xe3, 0xf9, 0xd6, 0x60, 0x29, 0xc6, 0xae, 0x32, 0x7e, + 0x94, 0xd4, 0xec, 0x9b, 0xb9, 0x46, 0xf9, 0xba, 0xb2, 0x4e, 0x23, 0xac, + 0xa7, 0xf3, 0xf1, 0x3f, 0xd2, 0x67, 0xa1, 0x79, 0xb2, 0x3b, 0x5b, 0xfe, + 0x93, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x1c, 0x5f, 0xf2, 0x31, 0x9c, 0x6b, + 0xbb, 0x4d, 0x15, 0xad, 0x98, 0x74, 0x44, 0xf9, 0x16, 0xff, 0xf3, 0x0b, + 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0xdd, 0xe0, 0x73, 0xf3, 0xae, + 0xcd, 0xce, 0xbf, 0xc1, 0xc5, 0xae, 0x13, 0x47, 0x5e, 0xd8, 0x09, 0x1d, + 0x4d, 0x44, 0x16, 0xe3, 0xa8, 0x2d, 0xb0, 0xc6, 0xf7, 0x43, 0x23, 0xaf, + 0xfb, 0x37, 0x1c, 0xff, 0xf7, 0x91, 0xd7, 0x2d, 0xa7, 0x54, 0x1e, 0x7c, + 0x8e, 0x6f, 0x86, 0x37, 0x91, 0xd7, 0xff, 0xe7, 0xdf, 0xf0, 0xf5, 0xe5, + 0x9a, 0x10, 0x3f, 0xd3, 0xa9, 0xa7, 0xf1, 0xd2, 0x1b, 0xf9, 0x38, 0x29, + 0xed, 0x1d, 0x7e, 0xe3, 0x8e, 0x41, 0xd4, 0x68, 0x86, 0xfa, 0x79, 0xee, + 0x57, 0x74, 0x09, 0xd7, 0xf2, 0x08, 0x71, 0x02, 0x75, 0x41, 0xbe, 0x90, + 0xa5, 0xf6, 0x4d, 0x2c, 0x3a, 0xff, 0xcf, 0x26, 0x33, 0x8d, 0x77, 0x69, + 0xa2, 0x60, 0xbf, 0x7f, 0xa7, 0x1f, 0xce, 0xbf, 0xc0, 0xdf, 0x89, 0x0b, + 0xc3, 0xaf, 0xfa, 0x27, 0xf0, 0xc0, 0x3d, 0xa3, 0xad, 0xee, 0x9f, 0x56, + 0xd9, 0x95, 0xf6, 0xed, 0x45, 0x0e, 0xac, 0x3c, 0xef, 0x15, 0xdf, 0xed, + 0x27, 0x51, 0x78, 0xa1, 0xd7, 0xff, 0x9e, 0x7e, 0xa4, 0x0e, 0x4c, 0x9c, + 0x43, 0xab, 0xc7, 0xf2, 0xc9, 0x95, 0xcd, 0xc3, 0xae, 0x07, 0xe5, 0x52, + 0x1a, 0xce, 0x0a, 0xdf, 0xec, 0x08, 0xe7, 0xbb, 0x87, 0x5f, 0xd3, 0xfd, + 0xdb, 0x71, 0xfc, 0xeb, 0xfb, 0x3d, 0xe8, 0xe6, 0x8e, 0xbf, 0x9c, 0x7f, + 0x9f, 0xff, 0x1d, 0x50, 0x88, 0xe1, 0x33, 0xdb, 0x2c, 0xb3, 0x10, 0xbb, + 0x13, 0x39, 0xf8, 0x5a, 0xf2, 0x13, 0x2d, 0x71, 0xdd, 0xcb, 0x84, 0x0b, + 0x21, 0x74, 0xa1, 0x87, 0x06, 0xa1, 0x35, 0xe4, 0xfd, 0x84, 0x1f, 0x61, + 0x7d, 0x79, 0x60, 0xe1, 0x57, 0xfe, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, + 0x13, 0x1d, 0xf4, 0x72, 0x36, 0x8e, 0xb3, 0x08, 0x88, 0x95, 0x8e, 0x75, + 0x2a, 0xfa, 0x27, 0x8e, 0x1d, 0x7e, 0xc8, 0x99, 0x16, 0x75, 0x21, 0xe3, + 0xf0, 0x86, 0xff, 0x76, 0x39, 0x3f, 0xd0, 0x7e, 0x75, 0xcf, 0xa3, 0xaf, + 0xbe, 0x7b, 0x3a, 0x75, 0xa3, 0xa6, 0xe3, 0x42, 0xb7, 0xa0, 0x67, 0x3a, + 0xff, 0xff, 0xfa, 0x5a, 0xee, 0x01, 0x9d, 0x77, 0x1b, 0x9a, 0xf9, 0x9b, + 0xcb, 0x48, 0x28, 0x75, 0xe7, 0x76, 0x9a, 0x2b, 0x1b, 0xe7, 0xfb, 0x0a, + 0x1d, 0x4d, 0x3c, 0xae, 0x13, 0xdf, 0xfb, 0x6f, 0x3c, 0x38, 0x08, 0x1f, + 0x1d, 0x4a, 0x26, 0xd4, 0xd2, 0x6d, 0xc6, 0xf9, 0x0c, 0x9f, 0x11, 0x5f, + 0xfc, 0x3e, 0x50, 0x10, 0x38, 0xd8, 0xe1, 0xd7, 0xfb, 0x93, 0xfb, 0x4f, + 0xbb, 0x4e, 0xa8, 0x3f, 0x77, 0x42, 0xbf, 0xa3, 0x6b, 0xd9, 0xbc, 0xc7, + 0x5f, 0xc0, 0xdb, 0x6f, 0x51, 0x52, 0x75, 0xfd, 0x9a, 0xde, 0x51, 0xd3, + 0xae, 0x8d, 0x87, 0x58, 0x3d, 0x3c, 0x41, 0x2d, 0xbf, 0xe8, 0xde, 0x53, + 0x49, 0xf9, 0x39, 0xd5, 0x08, 0xda, 0xc7, 0x84, 0x27, 0xbd, 0x12, 0xf1, + 0xd7, 0xfe, 0xc0, 0xf1, 0x01, 0x3f, 0xfa, 0x91, 0xd7, 0xcb, 0x7d, 0xfc, + 0x75, 0xff, 0xd3, 0xc7, 0xbe, 0x7d, 0x6f, 0xdd, 0xaf, 0xba, 0x3a, 0xff, + 0xb9, 0x1a, 0x7e, 0x0c, 0x48, 0xea, 0xe2, 0x21, 0xf6, 0x28, 0xde, 0x93, + 0xce, 0x75, 0xef, 0x93, 0xac, 0xeb, 0x83, 0xe3, 0xa9, 0x54, 0x98, 0xfe, + 0x42, 0xa7, 0x72, 0x54, 0x1c, 0x11, 0xfb, 0xff, 0x0b, 0x87, 0xb1, 0xb3, + 0xae, 0x27, 0x5f, 0xff, 0xf8, 0x13, 0xe3, 0x7e, 0x08, 0x36, 0xbe, 0x66, + 0xf2, 0xc0, 0x0f, 0xfa, 0x3a, 0xff, 0x9f, 0x71, 0xc0, 0xf5, 0xd9, 0x3a, + 0x82, 0x8e, 0xa1, 0x3d, 0xd3, 0xad, 0xfd, 0x3c, 0xd2, 0x55, 0x72, 0x73, + 0xaf, 0x84, 0x73, 0xc7, 0x52, 0xb2, 0x7a, 0x90, 0x6b, 0x7f, 0x4f, 0xf7, + 0x6d, 0xc7, 0xf3, 0xaf, 0xfe, 0x9b, 0xae, 0xbf, 0x76, 0x3c, 0x05, 0x9d, + 0x7f, 0xc9, 0x24, 0xe8, 0x16, 0xb4, 0x3a, 0xa1, 0x15, 0xf8, 0x67, 0xe4, + 0x5b, 0xdd, 0x46, 0x21, 0x90, 0xaf, 0x22, 0x1c, 0x8f, 0x65, 0xb0, 0xc9, + 0xe1, 0x07, 0x63, 0x0b, 0x72, 0xd1, 0x1b, 0xd4, 0x6b, 0xfe, 0x8c, 0xf3, + 0x6e, 0x10, 0x7f, 0x61, 0xab, 0x74, 0x84, 0xeb, 0xfb, 0x9c, 0x80, 0xe2, + 0xce, 0xbb, 0xef, 0xe7, 0x5e, 0xea, 0x2c, 0xeb, 0x4c, 0x75, 0x39, 0xac, + 0x00, 0xdd, 0xf9, 0xc6, 0x70, 0x68, 0xeb, 0xfe, 0x80, 0xf7, 0x03, 0xc7, + 0x69, 0xd4, 0x88, 0xef, 0xfc, 0xb0, 0x51, 0x74, 0x41, 0xe2, 0x7b, 0xda, + 0xfb, 0xa3, 0xaf, 0xb7, 0x9e, 0x14, 0x3a, 0x82, 0x78, 0x40, 0x1e, 0xbb, + 0xd0, 0x75, 0xf9, 0x78, 0x31, 0x23, 0xaf, 0x81, 0xec, 0xd1, 0xd7, 0xd1, + 0xc7, 0x13, 0xaf, 0xf3, 0xf2, 0x5f, 0xa6, 0xfa, 0x3a, 0xfb, 0x5a, 0x8f, + 0xce, 0xa8, 0x45, 0xda, 0x12, 0xf4, 0x84, 0x03, 0xec, 0x9a, 0x5f, 0x4b, + 0xf0, 0x48, 0xeb, 0xee, 0x7d, 0x8f, 0xce, 0xa8, 0x3c, 0x74, 0x23, 0xbf, + 0xc9, 0x3b, 0xaf, 0xff, 0xe0, 0xeb, 0xfe, 0x46, 0xf7, 0x26, 0x18, 0x09, + 0xd7, 0xd2, 0xf6, 0x7d, 0x3a, 0xf3, 0x63, 0xf3, 0xaf, 0x72, 0x16, 0x75, + 0x39, 0xed, 0x00, 0x8d, 0x91, 0xcb, 0xf4, 0x4f, 0xf7, 0x26, 0x3a, 0xf4, + 0x0c, 0x8e, 0xa9, 0x93, 0x58, 0xe1, 0x07, 0x4d, 0x06, 0x12, 0x3a, 0x2f, + 0xf1, 0x55, 0xff, 0xa3, 0x35, 0xf2, 0x10, 0x3f, 0x64, 0x75, 0xfc, 0x8c, + 0xea, 0x7c, 0x64, 0xea, 0x13, 0xef, 0xf2, 0x05, 0xfa, 0x03, 0xec, 0x69, + 0xd7, 0xdd, 0x81, 0x69, 0xd5, 0x23, 0xe7, 0xd1, 0x0f, 0x89, 0xaf, 0x9c, + 0x5e, 0x63, 0xaf, 0xc9, 0xe1, 0xc9, 0x1d, 0x7d, 0x0c, 0xc4, 0xc7, 0x5d, + 0xf5, 0x67, 0x5f, 0xf0, 0x3e, 0x78, 0x5f, 0xfc, 0x13, 0xaa, 0x74, 0x5c, + 0x28, 0x40, 0x84, 0xbd, 0x22, 0x11, 0x8b, 0xfd, 0x0c, 0x84, 0x0f, 0xc9, + 0x1d, 0x7f, 0x27, 0x37, 0xd4, 0x48, 0xeb, 0x6c, 0x3a, 0xb8, 0x7e, 0x5d, + 0x33, 0xda, 0x2d, 0xbc, 0x28, 0xa1, 0xd7, 0xd8, 0x14, 0xd8, 0x75, 0xd0, + 0xbc, 0x37, 0xae, 0x37, 0x6d, 0x1d, 0x48, 0x6e, 0x9c, 0xaa, 0xef, 0xe0, + 0xab, 0x99, 0x64, 0xaa, 0x43, 0x5c, 0xc8, 0xb5, 0xfe, 0x79, 0x0e, 0x7b, + 0xa8, 0x53, 0x06, 0x86, 0xf3, 0xef, 0xa3, 0xaf, 0xbe, 0xf5, 0xfc, 0x75, + 0x04, 0xdf, 0xf8, 0x72, 0xf4, 0x0c, 0xc7, 0x5c, 0x30, 0x75, 0xa6, 0x3a, + 0xa6, 0x3c, 0x0e, 0x0d, 0xb8, 0xa5, 0xff, 0xca, 0x20, 0xb7, 0x50, 0xb7, + 0xdf, 0xc7, 0x5e, 0xff, 0x36, 0x8e, 0xa5, 0x0f, 0x8f, 0x88, 0x97, 0xcb, + 0xd0, 0x16, 0x75, 0x94, 0x3a, 0xdb, 0x67, 0x5d, 0xc5, 0x0e, 0xa8, 0x3d, + 0xd4, 0x22, 0x00, 0x8f, 0xd1, 0x3b, 0xff, 0xee, 0xe4, 0xb5, 0x1e, 0x96, + 0x2b, 0xb8, 0xfe, 0x75, 0xff, 0xa4, 0x9e, 0xee, 0x6f, 0xe0, 0x41, 0xd7, + 0x66, 0x8e, 0xa8, 0x3d, 0x39, 0x1f, 0x56, 0x91, 0x8b, 0xe8, 0x52, 0x5f, + 0x92, 0x17, 0x0b, 0x3a, 0xd8, 0x75, 0x21, 0xee, 0x68, 0xa3, 0x6c, 0x96, + 0xa1, 0x58, 0x0e, 0x30, 0xa4, 0x24, 0xbb, 0x08, 0x07, 0x8d, 0x76, 0xf6, + 0xa2, 0x63, 0xa8, 0xeb, 0x2c, 0xea, 0xf1, 0x75, 0xb0, 0x2a, 0xfd, 0xfa, + 0x71, 0x14, 0x3a, 0xe7, 0x50, 0xea, 0x99, 0x12, 0xdd, 0x36, 0xfc, 0x88, + 0x4a, 0x2e, 0xf4, 0x1d, 0x7e, 0x8e, 0xe6, 0xc7, 0x3a, 0x9c, 0xde, 0x7e, + 0x2b, 0x7f, 0x27, 0xb3, 0xae, 0xa1, 0xd7, 0xf7, 0x40, 0xf3, 0xf5, 0x0e, + 0xbc, 0xcb, 0x2c, 0x95, 0x7f, 0xc1, 0x89, 0xfe, 0xe7, 0x5f, 0x72, 0x98, + 0x2f, 0xee, 0xc9, 0xce, 0xa0, 0xa2, 0xb5, 0xa9, 0x88, 0x97, 0x7a, 0x16, + 0x87, 0x56, 0x1e, 0x4b, 0x4b, 0xef, 0x93, 0x9b, 0x41, 0x3a, 0xfd, 0xd8, + 0xdd, 0xd5, 0xce, 0xbf, 0xfe, 0x8f, 0x68, 0x39, 0xe4, 0xe8, 0x33, 0x7f, + 0x1d, 0x5d, 0x3f, 0x9f, 0x15, 0x5b, 0x87, 0x5f, 0xec, 0xc6, 0xfd, 0xd9, + 0xdc, 0x3a, 0xe0, 0x68, 0xeb, 0xff, 0xf6, 0x06, 0x33, 0x7f, 0xbe, 0x41, + 0x04, 0xb3, 0x47, 0x5c, 0xbf, 0xce, 0xb9, 0xc4, 0xea, 0xe9, 0xab, 0x71, + 0x7b, 0xf2, 0xd3, 0xdf, 0xb9, 0xd5, 0x3a, 0x7c, 0x39, 0x09, 0xd5, 0x72, + 0x29, 0x84, 0x1c, 0xd4, 0x45, 0xbd, 0x08, 0x00, 0x10, 0x5f, 0x77, 0xc9, + 0x39, 0xd7, 0xf9, 0xa9, 0xa1, 0xcd, 0x8e, 0x75, 0xf4, 0x4e, 0xf2, 0x3a, + 0xec, 0xf1, 0xd7, 0xec, 0x9c, 0x73, 0x73, 0xab, 0x11, 0x63, 0xb9, 0x17, + 0x0c, 0xba, 0x42, 0x22, 0xb7, 0xbb, 0x01, 0x3a, 0xee, 0x68, 0xea, 0x39, + 0x0b, 0x6b, 0xfd, 0x03, 0x27, 0x5e, 0x04, 0xeb, 0xef, 0x2d, 0x7c, 0x3a, + 0xff, 0xef, 0xe0, 0x5a, 0xfe, 0xff, 0xe8, 0xc8, 0xeb, 0xd2, 0x4e, 0x9d, + 0x7d, 0xe1, 0xc9, 0x1d, 0x7e, 0xc0, 0x2a, 0x74, 0xe7, 0x5f, 0xfe, 0x4d, + 0x77, 0x02, 0x39, 0xb0, 0x73, 0x47, 0x54, 0x93, 0x45, 0x50, 0xc3, 0x72, + 0x29, 0x91, 0xb8, 0x36, 0x24, 0x1e, 0x2a, 0xa5, 0x53, 0x67, 0xe3, 0x11, + 0x82, 0x4f, 0x08, 0xb9, 0x11, 0x06, 0x1a, 0x19, 0x1f, 0x46, 0xf1, 0x99, + 0xa4, 0x39, 0xe6, 0x85, 0xe7, 0x21, 0x52, 0xb6, 0xee, 0xcb, 0x81, 0x78, + 0x77, 0x7e, 0xf4, 0xa9, 0x21, 0x18, 0xc8, 0xb5, 0x28, 0x0b, 0xd1, 0x97, + 0xb2, 0x93, 0xb6, 0x63, 0xf6, 0x35, 0xdb, 0xfe, 0x63, 0xc9, 0x9b, 0x5a, + 0x04, 0x1d, 0x7f, 0xff, 0xc0, 0x86, 0x3d, 0xa4, 0xeb, 0xa7, 0xb3, 0x9f, + 0xad, 0xe4, 0x75, 0x30, 0xa8, 0x76, 0x78, 0xdf, 0x02, 0x77, 0x7e, 0xe3, + 0x5d, 0xda, 0x68, 0xad, 0xef, 0xfc, 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, + 0x27, 0x0b, 0x31, 0x87, 0xfa, 0xb3, 0x3b, 0x95, 0x41, 0x3a, 0xdd, 0x3a, + 0xda, 0x3a, 0x80, 0x68, 0x36, 0xc4, 0x2f, 0x9a, 0xee, 0xd3, 0x45, 0xa3, + 0x7f, 0xfb, 0x03, 0xd7, 0x52, 0x69, 0x93, 0x40, 0x59, 0xd5, 0xc3, 0xf9, + 0xe9, 0x6d, 0xf3, 0x5c, 0x7f, 0x3a, 0xff, 0xa6, 0xc5, 0x7d, 0x73, 0x8f, + 0xe3, 0xaf, 0xe8, 0x71, 0x00, 0x70, 0xeb, 0x91, 0x43, 0xaf, 0xff, 0xd3, + 0xc7, 0xa0, 0x3c, 0x8e, 0xbe, 0x87, 0x3f, 0x3a, 0xff, 0xd1, 0xbb, 0xab, + 0xf4, 0x5d, 0x5e, 0x73, 0xaf, 0xfd, 0x1c, 0xff, 0x13, 0x39, 0xe0, 0x1d, + 0x50, 0x8d, 0x5e, 0xaa, 0x69, 0x12, 0xd9, 0x32, 0x63, 0x5a, 0x87, 0x5d, + 0xfe, 0xef, 0x40, 0xa2, 0xe3, 0x47, 0x5f, 0xff, 0x93, 0x43, 0x9b, 0x1f, + 0xc3, 0x9a, 0xeb, 0xcc, 0x75, 0x62, 0x22, 0x26, 0x34, 0xbe, 0xcf, 0xdf, + 0xa7, 0x5d, 0xdd, 0x1d, 0x66, 0x15, 0x0a, 0xea, 0xd5, 0xb3, 0xac, 0x84, + 0xeb, 0x48, 0xa6, 0x21, 0x59, 0xe7, 0x63, 0x44, 0xf4, 0x2d, 0xf6, 0xc8, + 0xfe, 0x90, 0xdf, 0x35, 0xdd, 0xa6, 0x8b, 0x6a, 0xff, 0xfe, 0x87, 0xf4, + 0x76, 0x34, 0x89, 0x24, 0xe6, 0x04, 0xeb, 0xfb, 0xb0, 0xb8, 0x40, 0x9d, + 0x5c, 0x45, 0x76, 0x8b, 0x7c, 0xad, 0x7f, 0xee, 0xa0, 0x5e, 0x41, 0xea, + 0x2c, 0xeb, 0xe8, 0xd9, 0x88, 0x75, 0xff, 0x44, 0xa3, 0x93, 0xc7, 0x27, + 0x3a, 0xff, 0xa3, 0x9f, 0x35, 0x1d, 0x74, 0x3a, 0xff, 0x75, 0x1e, 0x5e, + 0x49, 0xce, 0xac, 0x4c, 0xc5, 0xa6, 0x1c, 0x3d, 0x12, 0x16, 0x4e, 0x76, + 0xce, 0x2f, 0xe5, 0x1f, 0x81, 0x00, 0x9d, 0x7f, 0x0e, 0xda, 0x73, 0x14, + 0x3a, 0xfc, 0x93, 0xae, 0x1a, 0x75, 0xf9, 0xf7, 0x97, 0xdd, 0x1d, 0x66, + 0x14, 0x45, 0x68, 0x96, 0xf8, 0xbf, 0x61, 0x3d, 0x30, 0x9a, 0x6f, 0xf1, + 0x83, 0xdc, 0xbe, 0x9d, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xb9, 0x6c, 0xc0, + 0x4f, 0x27, 0x05, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x17, 0x6d, 0xff, 0x24, + 0xa4, 0x83, 0xfc, 0x48, 0xeb, 0x31, 0x87, 0xd4, 0xe6, 0x75, 0x0e, 0xc5, + 0x3a, 0x72, 0x99, 0x4f, 0x31, 0x06, 0x36, 0x85, 0x29, 0x1a, 0x89, 0x5b, + 0x78, 0xab, 0xc2, 0xdf, 0xb2, 0xf4, 0xc6, 0x5e, 0xf6, 0x9d, 0x7d, 0x09, + 0x2b, 0xfc, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x54, 0xf7, 0x83, 0x3a, 0xce, + 0xb7, 0x8e, 0xbf, 0xe8, 0x79, 0xfe, 0x6f, 0xa8, 0x09, 0xd4, 0x87, 0x96, + 0x22, 0x17, 0xcd, 0x77, 0x69, 0xa2, 0xb9, 0xbf, 0xcc, 0x67, 0x1a, 0xee, + 0xd3, 0x45, 0x9d, 0x79, 0xde, 0x47, 0x5f, 0xc9, 0xac, 0x17, 0x64, 0xea, + 0xe2, 0x2c, 0x7a, 0x5a, 0x27, 0xfe, 0x1a, 0xbf, 0xfd, 0xe8, 0xd7, 0xc0, + 0x6b, 0xd1, 0x34, 0xc8, 0x75, 0xfc, 0x8b, 0x9c, 0x1c, 0x91, 0xd7, 0xfa, + 0x3b, 0xf1, 0x6a, 0xda, 0xa3, 0xc7, 0x56, 0x22, 0xe7, 0xa9, 0xbb, 0x0b, + 0xaf, 0xdc, 0xcf, 0x22, 0xce, 0xbe, 0x71, 0x80, 0x9d, 0x7f, 0x64, 0xd0, + 0xb8, 0xfa, 0x75, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0x42, 0xbf, 0xf6, 0x2f, + 0x1f, 0x93, 0xfc, 0xdd, 0x67, 0x5f, 0xf2, 0x6f, 0xaf, 0x0c, 0x2f, 0x47, + 0x5d, 0x26, 0x31, 0x15, 0x9d, 0x33, 0xfd, 0x06, 0xff, 0xee, 0xa2, 0xf3, + 0x5f, 0x37, 0x96, 0x78, 0xeb, 0xe9, 0x77, 0xee, 0x8e, 0xa8, 0x3e, 0xac, + 0x46, 0xbe, 0x56, 0xfb, 0x0b, 0x3a, 0xfe, 0xee, 0xb5, 0x9c, 0x9c, 0xeb, + 0xa1, 0x93, 0xab, 0x0f, 0x11, 0x0b, 0xac, 0xc4, 0xeb, 0x99, 0xe1, 0x68, + 0xc8, 0x68, 0xa4, 0x3d, 0x78, 0x62, 0xb2, 0x6e, 0x8f, 0xbc, 0x36, 0x86, + 0x14, 0xfa, 0x20, 0xf3, 0x55, 0xff, 0xcc, 0x75, 0xf4, 0x39, 0xef, 0x47, + 0xe7, 0x5f, 0xfe, 0x61, 0x6f, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x7c, + 0xa6, 0xaf, 0x2e, 0x2b, 0xce, 0x87, 0x2e, 0x16, 0x7d, 0x44, 0xb9, 0x37, + 0x3a, 0xff, 0xfa, 0x53, 0xaa, 0xd0, 0xad, 0xce, 0xde, 0x7c, 0xf9, 0xdd, + 0xb3, 0xaa, 0x47, 0xf5, 0xf8, 0xb5, 0xfb, 0x39, 0x99, 0x31, 0xd6, 0x63, + 0xa7, 0x93, 0xf4, 0x8e, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x59, 0x5f, 0xf9, + 0xe4, 0xc6, 0x71, 0xae, 0xed, 0x34, 0x4d, 0xd6, 0x63, 0x0f, 0xf5, 0x66, + 0x74, 0xd4, 0x68, 0x24, 0x2a, 0x2f, 0xdc, 0x6b, 0xbb, 0x4d, 0x12, 0xb5, + 0xf8, 0x60, 0x2f, 0xd3, 0xaf, 0xcc, 0x2d, 0xe4, 0xc6, 0x1e, 0xc2, 0x19, + 0xdf, 0xfb, 0xd8, 0xc6, 0x71, 0x27, 0x75, 0x9d, 0x7f, 0xf9, 0x58, 0x56, + 0x55, 0x1a, 0xc7, 0x92, 0x67, 0x30, 0xeb, 0xff, 0x26, 0x80, 0xb1, 0x4d, + 0x80, 0x73, 0xaf, 0xe8, 0x17, 0x6b, 0xab, 0x9d, 0x52, 0x3e, 0xb5, 0x9f, + 0x5c, 0x1e, 0x1d, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0x97, 0x2f, 0xf9, 0x1e, + 0x5e, 0x18, 0x5e, 0x8e, 0xbf, 0x4b, 0x6d, 0x3a, 0xe7, 0x5e, 0x8d, 0xb8, + 0x3a, 0xf2, 0x0c, 0x1d, 0x52, 0x3d, 0xf0, 0x94, 0xec, 0x1d, 0xbf, 0xff, + 0x3f, 0x90, 0x12, 0x14, 0x94, 0x78, 0x41, 0x23, 0xaf, 0xe9, 0x77, 0x07, + 0x1a, 0x75, 0xe9, 0x77, 0xc7, 0x5d, 0xd8, 0x43, 0xc7, 0xe9, 0x5d, 0xff, + 0xc2, 0x9f, 0xeb, 0x90, 0x92, 0x7d, 0x1d, 0x58, 0x7d, 0xc8, 0x59, 0x79, + 0xe4, 0xc2, 0xaf, 0x56, 0x31, 0x10, 0xc0, 0x91, 0x16, 0x0b, 0x74, 0xcd, + 0xe1, 0x2b, 0xa3, 0x1f, 0x46, 0x0f, 0x66, 0x11, 0x5f, 0x72, 0xe5, 0xab, + 0x5f, 0xfc, 0xc3, 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x8e, 0xef, 0xfb, + 0xdd, 0xc9, 0x30, 0xe3, 0xa3, 0xaf, 0xe5, 0x50, 0xc3, 0x70, 0x4e, 0xb8, + 0x1d, 0x3a, 0xfe, 0x54, 0x0e, 0x75, 0xfc, 0x75, 0xff, 0xfd, 0xe9, 0x20, + 0x7a, 0x9b, 0x3e, 0x60, 0x78, 0x80, 0x69, 0xd7, 0xfb, 0x19, 0xd4, 0x0f, + 0xb4, 0x75, 0xfe, 0x71, 0xfd, 0xf8, 0xff, 0x4e, 0xbf, 0xf2, 0x73, 0xe6, + 0x87, 0x17, 0x0d, 0x3a, 0xff, 0xd0, 0x20, 0xf2, 0x3e, 0xc7, 0x91, 0xd7, + 0xcd, 0x77, 0x69, 0xa2, 0xa1, 0xbf, 0xec, 0xee, 0x0b, 0xf3, 0x88, 0x75, + 0x28, 0x8d, 0xd6, 0x9f, 0x70, 0xf7, 0x45, 0xb7, 0x4b, 0x0e, 0xbf, 0xe9, + 0x79, 0x38, 0xed, 0x41, 0x3a, 0xff, 0xf3, 0xaf, 0x38, 0x38, 0x9b, 0x13, + 0x8e, 0x75, 0xff, 0xdd, 0x1c, 0x9b, 0xdd, 0xce, 0x26, 0x8e, 0xbf, 0x6e, + 0x28, 0xb4, 0x3a, 0xa1, 0x16, 0x18, 0x8e, 0x88, 0x77, 0xfa, 0x3c, 0xfd, + 0xf8, 0x18, 0x3a, 0xff, 0xc0, 0xf8, 0xe3, 0x9b, 0x5f, 0x3a, 0x03, 0xaf, + 0xf4, 0xa3, 0x93, 0xc7, 0x27, 0x3a, 0xff, 0xed, 0x6b, 0x07, 0xda, 0xc9, + 0x27, 0x4e, 0xbf, 0xfe, 0x8f, 0xf0, 0x7e, 0x3f, 0xbe, 0x77, 0x3f, 0x73, + 0xae, 0x19, 0xce, 0xa8, 0x46, 0xf6, 0x1a, 0x22, 0x10, 0xa9, 0x5f, 0xdb, + 0x1d, 0x7d, 0x65, 0xce, 0xbf, 0xff, 0xc9, 0x1e, 0x7e, 0xb1, 0xae, 0xe0, + 0xfb, 0xe7, 0xf2, 0xd1, 0xd6, 0xc4, 0x44, 0x90, 0x97, 0xdf, 0x77, 0xd9, + 0x39, 0xd7, 0xec, 0x9d, 0xc7, 0x61, 0xd7, 0xff, 0xff, 0xfa, 0x25, 0xf3, + 0xdd, 0x48, 0xd7, 0xcc, 0x03, 0x63, 0x67, 0xcc, 0xe7, 0x33, 0x60, 0x1f, + 0xa7, 0x5f, 0x74, 0x5f, 0x68, 0xea, 0xc4, 0xc0, 0xc4, 0x8b, 0x45, 0x1e, + 0x84, 0xb5, 0xff, 0xff, 0x01, 0xd5, 0xd2, 0x7e, 0xba, 0x7a, 0x3a, 0x9e, + 0xd6, 0x04, 0xeb, 0x30, 0xa8, 0x5f, 0x6a, 0x56, 0xcb, 0x95, 0x42, 0xd0, + 0x5f, 0x3a, 0xf0, 0x4c, 0xb2, 0x31, 0x06, 0x9f, 0x6e, 0x2b, 0xc8, 0x73, + 0x2c, 0xb7, 0xa6, 0x63, 0x19, 0x16, 0xa1, 0x97, 0xe8, 0xca, 0x76, 0xd0, + 0x6f, 0x9a, 0xee, 0xd3, 0x45, 0x51, 0x7f, 0xb9, 0x1b, 0x37, 0x96, 0x78, + 0xea, 0xe1, 0xf1, 0x00, 0xb6, 0xff, 0xcf, 0x26, 0x33, 0x8d, 0x77, 0x69, + 0xa2, 0x6b, 0xbc, 0xb7, 0xf1, 0xd6, 0x63, 0x11, 0x0e, 0xb2, 0x27, 0x4a, + 0xbf, 0x71, 0xae, 0xed, 0x34, 0x55, 0x97, 0xfd, 0x12, 0x8e, 0x4f, 0x1c, + 0x9c, 0xeb, 0x31, 0x87, 0xd8, 0x26, 0x77, 0xfe, 0x63, 0xb1, 0xbf, 0xa3, + 0xae, 0xae, 0x75, 0xff, 0xcc, 0x3c, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, + 0x12, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x69, 0x5f, 0xf9, 0xe4, 0xc6, 0x71, + 0xae, 0xed, 0x34, 0x4f, 0xb6, 0x63, 0x0f, 0xf5, 0x66, 0x77, 0xff, 0x98, + 0x5b, 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xa1, 0x2f, 0xdd, 0x49, 0xe3, + 0x87, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, 0x28, 0xfb, 0xfe, 0x89, 0x47, 0x27, + 0x8e, 0x4e, 0x75, 0xff, 0x86, 0x26, 0x81, 0x89, 0xbb, 0x07, 0x5f, 0xff, + 0xd8, 0x1e, 0xc7, 0xd6, 0x3c, 0x2f, 0xfe, 0xb5, 0x1f, 0x95, 0x7e, 0x61, + 0x6f, 0x26, 0x21, 0x32, 0xdc, 0x27, 0x13, 0x3f, 0x1c, 0xed, 0x9e, 0x54, + 0x36, 0x46, 0xf3, 0xce, 0x16, 0xc8, 0xcb, 0x14, 0x54, 0x9f, 0xa2, 0x6c, + 0x7e, 0xfb, 0xc2, 0x85, 0x09, 0xe6, 0x42, 0xec, 0x33, 0xbf, 0x28, 0xf4, + 0x70, 0x97, 0xf9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x88, 0xaf, 0xec, 0xe3, + 0x5d, 0xda, 0x68, 0x8a, 0xef, 0xf9, 0x5d, 0x8c, 0xe3, 0x5d, 0xda, 0x68, + 0xae, 0x29, 0x84, 0x40, 0x39, 0xc5, 0xff, 0xef, 0xe0, 0x5a, 0xc3, 0xfb, + 0xff, 0xa3, 0x23, 0xaf, 0x98, 0x9e, 0x65, 0x73, 0xac, 0x9b, 0x9f, 0xaf, + 0xe9, 0xb7, 0xd9, 0xd7, 0xf1, 0xd7, 0xfb, 0x13, 0x9f, 0xfe, 0x0d, 0x1d, + 0x65, 0x40, 0x9e, 0xa6, 0x88, 0x2f, 0xff, 0xef, 0x69, 0x3a, 0xe9, 0x24, + 0x1f, 0x03, 0xbc, 0xc3, 0xaf, 0xdc, 0x6b, 0xbb, 0x4d, 0x14, 0xf5, 0xfe, + 0x5a, 0x04, 0x0f, 0xc9, 0x1d, 0x72, 0xd0, 0xea, 0x83, 0xc7, 0x69, 0x95, + 0xff, 0xfe, 0x94, 0x7b, 0x40, 0x5b, 0x53, 0xf8, 0xce, 0xa0, 0x1a, 0x75, + 0xff, 0xfd, 0xce, 0x03, 0x9c, 0x81, 0xc5, 0x13, 0xbd, 0xcf, 0xa7, 0x5f, + 0xfc, 0x92, 0xc1, 0xfe, 0x16, 0x9c, 0x91, 0xd7, 0xfa, 0x51, 0xc9, 0xe3, + 0x93, 0x9d, 0x7d, 0xf0, 0x5e, 0x47, 0x5f, 0x9f, 0x3a, 0x8b, 0x3a, 0xb4, + 0x78, 0xfb, 0x08, 0xaa, 0x11, 0x3f, 0x8f, 0x77, 0xfd, 0x02, 0xdc, 0xd9, + 0x9e, 0xd1, 0xd7, 0xe7, 0x9e, 0x38, 0x03, 0xa9, 0x54, 0xac, 0xee, 0x0a, + 0xf1, 0x61, 0xaf, 0x5b, 0x90, 0xa3, 0x03, 0xae, 0x0c, 0x38, 0x76, 0x10, + 0xed, 0x9c, 0x5f, 0xfe, 0x79, 0x30, 0x11, 0x76, 0x75, 0xa8, 0xfc, 0xeb, + 0xff, 0xdf, 0xfe, 0x0d, 0x31, 0xf4, 0x5d, 0x63, 0x07, 0x5f, 0xfc, 0x39, + 0xfb, 0x8f, 0xec, 0x2d, 0x16, 0x75, 0x71, 0x12, 0x3e, 0x4d, 0xa6, 0x13, + 0x96, 0x0c, 0x25, 0xd2, 0x1b, 0x97, 0x07, 0x0e, 0xbf, 0xf9, 0x03, 0xc7, + 0xdd, 0x8e, 0x72, 0x27, 0x3a, 0x98, 0x3d, 0xbe, 0x8a, 0xdc, 0x18, 0x3a, + 0xff, 0xfd, 0xd8, 0xe6, 0x49, 0x1f, 0xd8, 0x14, 0x03, 0x4a, 0xbf, 0x44, + 0xbf, 0x04, 0x8e, 0xbe, 0x6b, 0xbb, 0x4d, 0x15, 0x9d, 0x4c, 0x7a, 0xbc, + 0x28, 0xbe, 0xf2, 0x2f, 0x47, 0x5f, 0xd3, 0xae, 0x06, 0x5a, 0x3a, 0xfd, + 0x9e, 0xd7, 0xdd, 0x1d, 0x7a, 0x27, 0x43, 0xaf, 0xde, 0xff, 0xe8, 0xc8, + 0xeb, 0xc0, 0x7d, 0x1d, 0x7f, 0xd9, 0x24, 0x02, 0xba, 0xb7, 0xfa, 0xce, + 0xbf, 0x64, 0xd3, 0x83, 0xf3, 0xac, 0xc4, 0x2a, 0x21, 0x08, 0xae, 0x42, + 0x9f, 0x72, 0x3e, 0x10, 0xac, 0xb7, 0xa5, 0x2e, 0x36, 0x25, 0x5a, 0x1b, + 0xfa, 0x83, 0x7f, 0xee, 0xa7, 0x9f, 0x93, 0xc2, 0x04, 0xeb, 0xf7, 0x90, + 0x71, 0x67, 0x5f, 0x49, 0xc5, 0x8c, 0x3e, 0x2d, 0xa3, 0xdb, 0xff, 0x3c, + 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x89, 0x16, 0xff, 0xcf, 0xe6, 0x21, 0x38, + 0x9e, 0x01, 0xd4, 0xc2, 0x21, 0xdd, 0x2a, 0xfe, 0xce, 0x35, 0xdd, 0xa6, + 0x8b, 0x26, 0xff, 0xf7, 0xb5, 0xf7, 0x4c, 0x64, 0xe8, 0x32, 0xd1, 0xd4, + 0xc2, 0x21, 0x70, 0xe2, 0xff, 0xff, 0x3a, 0x78, 0x1c, 0x7d, 0x30, 0xde, + 0xa7, 0x22, 0x5a, 0x3a, 0xfe, 0xce, 0x35, 0xdd, 0xa6, 0x8b, 0x62, 0xff, + 0xfe, 0x54, 0x77, 0xe0, 0xe7, 0x3d, 0xae, 0xcd, 0xf3, 0xe7, 0x76, 0xce, + 0xbd, 0xc0, 0x74, 0xeb, 0xbc, 0xc4, 0x22, 0x1b, 0x8d, 0x54, 0xc2, 0x3b, + 0x52, 0x17, 0xd7, 0xb3, 0x58, 0x75, 0xf3, 0x5d, 0xda, 0x68, 0xb6, 0xef, + 0xb5, 0x3b, 0xf0, 0xea, 0xe1, 0xe7, 0xf8, 0xb6, 0xfe, 0x4e, 0xf9, 0x3f, + 0x01, 0xd7, 0xfd, 0x12, 0x8e, 0x4f, 0x1c, 0x9c, 0xeb, 0x31, 0x24, 0x78, + 0xe3, 0x4c, 0xc4, 0x42, 0x5b, 0x7f, 0xfb, 0x07, 0xf6, 0x16, 0xe1, 0xcc, + 0x15, 0x0e, 0xbc, 0xaa, 0xe8, 0x4e, 0xbd, 0x3f, 0x50, 0xeb, 0xff, 0x2a, + 0x95, 0x4a, 0xd3, 0xdd, 0xc1, 0x8f, 0xce, 0xbf, 0xa0, 0x64, 0x10, 0x2c, + 0xeb, 0xe6, 0xbb, 0xb4, 0xd1, 0x78, 0x5f, 0xf9, 0xfd, 0x1b, 0x39, 0xcc, + 0xdf, 0x47, 0x57, 0x0f, 0xb4, 0x4b, 0x6f, 0xbd, 0xb7, 0x9d, 0x3a, 0xfc, + 0xb8, 0x19, 0x39, 0xd7, 0xfa, 0x50, 0x3e, 0xd8, 0xed, 0x3a, 0xff, 0x47, + 0x9f, 0xbf, 0x03, 0x07, 0x5f, 0xfb, 0xea, 0xf7, 0x97, 0xb0, 0x7d, 0xa3, + 0xae, 0xc5, 0x0e, 0xa8, 0x3d, 0x7c, 0x41, 0xbe, 0x49, 0xf1, 0x67, 0x5f, + 0xb0, 0x7f, 0xda, 0x83, 0xaf, 0xd1, 0xf4, 0x0f, 0xa3, 0xaf, 0xff, 0x62, + 0xe1, 0xbf, 0x30, 0x41, 0x2c, 0xd1, 0xd7, 0xff, 0x67, 0x7a, 0xf2, 0x5a, + 0x47, 0x24, 0x75, 0xd1, 0xf9, 0xd5, 0x23, 0xd8, 0xf2, 0x15, 0x2a, 0x15, + 0xce, 0xaa, 0x88, 0x15, 0x78, 0xe4, 0xe9, 0x99, 0x09, 0x9d, 0xc8, 0x50, + 0x92, 0x62, 0x55, 0x99, 0xf6, 0x11, 0x4e, 0x41, 0xf9, 0x08, 0x94, 0xe8, + 0xa3, 0xd0, 0xa1, 0xbf, 0xdb, 0xb1, 0x9f, 0xbf, 0x34, 0x75, 0xfe, 0xfd, + 0x89, 0xa5, 0x03, 0xe3, 0xa9, 0x84, 0xd5, 0x62, 0x1d, 0x7c, 0x35, 0xbc, + 0x99, 0xb9, 0xd7, 0xcd, 0x77, 0x69, 0xa2, 0xf4, 0xbf, 0xf2, 0x7b, 0xa2, + 0xf2, 0xfd, 0xff, 0x3a, 0xb8, 0x7d, 0x6b, 0x2d, 0xbc, 0xb4, 0xf1, 0xd7, + 0xfc, 0xfe, 0x94, 0x29, 0xe4, 0x9c, 0xea, 0x59, 0xea, 0x08, 0xdd, 0xfb, + 0x17, 0xd7, 0x09, 0xd4, 0x14, 0xd0, 0xf2, 0x10, 0xdf, 0x5d, 0xb6, 0x88, + 0x6f, 0xff, 0xf9, 0x36, 0x60, 0xb0, 0x1c, 0x0f, 0x71, 0x6b, 0x79, 0x60, + 0x9d, 0x4c, 0x22, 0xb3, 0x11, 0xea, 0x1b, 0x63, 0xf9, 0xe1, 0x7f, 0x28, + 0x4c, 0x64, 0xea, 0x73, 0x61, 0x2c, 0x92, 0x91, 0x26, 0x8c, 0x1f, 0x90, + 0xc2, 0x5c, 0x2a, 0x3a, 0x47, 0xfc, 0x69, 0xa3, 0x18, 0xce, 0x90, 0xc1, + 0x3a, 0x76, 0xcc, 0xa2, 0x5b, 0x81, 0xd3, 0xaf, 0xfe, 0x04, 0x4c, 0x39, + 0xb1, 0xd6, 0xb4, 0x3a, 0xfb, 0x3a, 0xfe, 0x3a, 0xff, 0x62, 0x73, 0xff, + 0xc1, 0xa3, 0xac, 0xa8, 0x51, 0x13, 0x02, 0x89, 0xa2, 0x0b, 0xef, 0x46, + 0xf3, 0x9d, 0x7f, 0xde, 0xd6, 0x6f, 0x2e, 0x81, 0x43, 0xa9, 0x0f, 0x78, + 0x48, 0xef, 0xa3, 0x64, 0x48, 0xeb, 0xf7, 0x1a, 0xee, 0xd3, 0x44, 0x47, + 0x7f, 0xfd, 0xd0, 0x6b, 0x58, 0xb1, 0xcd, 0x9f, 0x21, 0x58, 0x3a, 0xff, + 0xa2, 0x7e, 0x67, 0xbc, 0x9e, 0x3a, 0xf0, 0xc6, 0xe7, 0x54, 0x8f, 0x4c, + 0x27, 0x17, 0xfd, 0x9c, 0xcd, 0x63, 0x8c, 0xe7, 0x5e, 0xc0, 0xac, 0xeb, + 0xff, 0xfd, 0xd7, 0x4f, 0x47, 0x47, 0x3d, 0xd4, 0xee, 0x23, 0x27, 0x5f, + 0xff, 0xfe, 0xf7, 0x91, 0x7c, 0x4c, 0xdc, 0x41, 0xe8, 0xef, 0xcd, 0x89, + 0xe9, 0xa0, 0xea, 0x84, 0x6c, 0x62, 0xed, 0xfe, 0x75, 0xe7, 0x25, 0x0b, + 0x3a, 0xe9, 0xd6, 0x55, 0xcc, 0xb2, 0x55, 0xff, 0x98, 0x6f, 0x52, 0x6e, + 0xc4, 0xec, 0x7e, 0x6b, 0xd9, 0x17, 0xbe, 0xd9, 0x1e, 0x83, 0xaa, 0x47, + 0xfa, 0x8b, 0x77, 0xf6, 0x3a, 0xf3, 0x7f, 0x1d, 0x7f, 0x9d, 0x8d, 0x27, + 0x1f, 0xf3, 0xac, 0xae, 0x75, 0xff, 0x46, 0x6f, 0x0f, 0x27, 0x91, 0xd4, + 0xac, 0x9e, 0x48, 0x44, 0xef, 0xe5, 0x71, 0xce, 0xbf, 0x8e, 0xbf, 0xa1, + 0x4c, 0x14, 0x50, 0xeb, 0xfb, 0x3d, 0xb5, 0xec, 0xe9, 0xd5, 0x88, 0x89, + 0x12, 0xed, 0x16, 0x5f, 0xff, 0xcd, 0x63, 0x8e, 0x29, 0xe6, 0x39, 0x1e, + 0x17, 0xfc, 0xea, 0x56, 0xd7, 0xac, 0x15, 0x50, 0xae, 0x88, 0x4c, 0x48, + 0x83, 0x08, 0x9a, 0x67, 0xbc, 0x2a, 0x90, 0x8a, 0x63, 0x6e, 0x43, 0xcf, + 0xa4, 0x2f, 0x0d, 0xdf, 0xc8, 0x44, 0xb3, 0x4f, 0x9e, 0x85, 0x86, 0xc2, + 0xeb, 0xb6, 0xba, 0x75, 0xfb, 0x8d, 0x77, 0x69, 0xa2, 0x2e, 0xbf, 0x7b, + 0xff, 0xa3, 0x22, 0xaf, 0xda, 0xf7, 0x63, 0xf3, 0xaf, 0xcf, 0x3c, 0x70, + 0x07, 0x59, 0x89, 0xd1, 0x8b, 0x83, 0x2e, 0x66, 0x02, 0xad, 0xb2, 0x8a, + 0x61, 0x51, 0x44, 0xa3, 0xd5, 0xbf, 0xf9, 0x6f, 0x26, 0x33, 0x8d, 0x77, + 0x69, 0xa2, 0x66, 0xbf, 0x95, 0x65, 0x68, 0xa8, 0xd4, 0x78, 0xeb, 0xdb, + 0xc6, 0x8e, 0xbc, 0xd4, 0x59, 0xd7, 0xca, 0xaf, 0x38, 0x9d, 0x76, 0xda, + 0xb2, 0x75, 0xd8, 0x03, 0xaf, 0xff, 0x76, 0x16, 0xfe, 0xcd, 0xff, 0x5f, + 0xde, 0x9d, 0x7f, 0x7b, 0x27, 0xcf, 0xe6, 0x3a, 0xff, 0x7c, 0xc1, 0x7e, + 0x7f, 0xb6, 0x75, 0xff, 0xf9, 0x6f, 0xdc, 0xdf, 0xfe, 0xb2, 0xfd, 0x9b, + 0xa0, 0x3a, 0x82, 0x89, 0x0c, 0x37, 0xbb, 0x58, 0x75, 0xdb, 0x5e, 0x3a, + 0xca, 0x93, 0xad, 0xfc, 0x1a, 0xd0, 0x0c, 0xdf, 0xff, 0xf9, 0x06, 0x1a, + 0x30, 0xbf, 0x91, 0xce, 0x26, 0xce, 0x3b, 0xfe, 0x75, 0x2b, 0x2a, 0x8d, + 0x9a, 0x3c, 0x82, 0xb3, 0x26, 0xf6, 0x17, 0xee, 0x45, 0xfa, 0x17, 0x89, + 0xef, 0xe6, 0x60, 0x47, 0x3c, 0x75, 0xf3, 0xf5, 0x26, 0x3a, 0xfb, 0xb3, + 0x40, 0x4e, 0xac, 0x3e, 0xe6, 0x95, 0xb9, 0x0d, 0xfe, 0x6a, 0x60, 0x87, + 0xb0, 0x75, 0x1d, 0x7e, 0xeb, 0xfa, 0x5f, 0x9d, 0x7f, 0xfb, 0xe7, 0x5d, + 0x3d, 0xf8, 0x04, 0x5e, 0x47, 0x56, 0x22, 0xb1, 0xa6, 0x08, 0x14, 0xb2, + 0x8b, 0xff, 0xff, 0xff, 0xff, 0xca, 0xbd, 0x51, 0x8a, 0xbd, 0x54, 0xad, + 0x15, 0xa3, 0x55, 0x30, 0xab, 0x95, 0x5c, 0x9f, 0x6b, 0x00, 0x15, 0x6b, + 0x1b, 0x7b, 0xfd, 0xea, 0xaa, 0x21, 0x54, 0xae, 0xab, 0x7b, 0xe7, 0xce, + 0xed, 0x9d, 0x7f, 0xfe, 0xff, 0x79, 0x74, 0x11, 0xc6, 0x3a, 0x8d, 0x7e, + 0x1d, 0x7f, 0xf6, 0xec, 0xc7, 0x82, 0x8a, 0xfa, 0x85, 0x9d, 0x7f, 0xff, + 0xe4, 0x5a, 0x73, 0xa0, 0xd4, 0xa3, 0x67, 0x20, 0x7d, 0xdc, 0x91, 0xd7, + 0xfe, 0x4f, 0x23, 0x50, 0x3e, 0xc6, 0x9d, 0x58, 0x8f, 0x0f, 0x24, 0x6d, + 0x36, 0x5f, 0x7b, 0x6f, 0x3a, 0x75, 0xff, 0xfe, 0x71, 0x68, 0xe0, 0x7a, + 0x0f, 0x9d, 0x89, 0x72, 0x27, 0x3a, 0xb1, 0x10, 0xa0, 0x24, 0xbf, 0xff, + 0xce, 0xa0, 0xe7, 0xe0, 0xd7, 0xc9, 0x27, 0x61, 0xa2, 0xe7, 0x5f, 0x79, + 0x3a, 0x87, 0x5f, 0xf3, 0xf2, 0x5f, 0x31, 0xa1, 0xc3, 0xa9, 0x54, 0xb8, + 0x0d, 0x11, 0x95, 0xe4, 0x69, 0x1d, 0x85, 0xbb, 0x91, 0x0b, 0x08, 0x08, + 0x2d, 0xc3, 0xaf, 0xef, 0x62, 0xf7, 0xc5, 0x9d, 0x6e, 0xe1, 0xbd, 0x41, + 0x0b, 0xfc, 0x00, 0xbc, 0xb4, 0x92, 0x3a, 0xff, 0xfc, 0x14, 0x19, 0xf3, + 0x48, 0xfd, 0x61, 0x96, 0x59, 0x2a, 0xfe, 0xf7, 0x62, 0x7e, 0x80, 0xeb, + 0xfb, 0x79, 0x6b, 0xf0, 0x4c, 0x75, 0xff, 0x4f, 0x9f, 0x84, 0x0f, 0xc9, + 0x1d, 0x79, 0xdd, 0xa6, 0x8b, 0x3e, 0xfe, 0xfd, 0xc6, 0x48, 0xb3, 0xaa, + 0x74, 0x46, 0xb4, 0xeb, 0xf2, 0x7b, 0xff, 0x27, 0x62, 0x49, 0xe8, 0xf6, + 0x8e, 0xbf, 0xfd, 0xce, 0xbf, 0xcc, 0xd8, 0x39, 0xac, 0x13, 0xaf, 0xfe, + 0xd7, 0x92, 0x66, 0x5c, 0x31, 0xbe, 0x8e, 0xa4, 0x44, 0x80, 0x12, 0xaf, + 0x32, 0xcb, 0x25, 0x5f, 0xf9, 0xe5, 0xa1, 0xc6, 0x87, 0x38, 0x53, 0x05, + 0xfd, 0xfb, 0x68, 0x0b, 0xc0, 0x9d, 0x7f, 0xbd, 0xdc, 0xd9, 0xf2, 0x4b, + 0x3a, 0xb0, 0xf8, 0x40, 0x55, 0x7f, 0xed, 0xe4, 0x20, 0xff, 0xe3, 0x57, + 0xf9, 0xd7, 0x42, 0x87, 0x54, 0x1e, 0xd4, 0xe8, 0x97, 0xfb, 0xa8, 0x11, + 0x77, 0x98, 0xeb, 0xfc, 0x1e, 0x81, 0xff, 0xdb, 0xc3, 0xaa, 0x0f, 0x9d, + 0x0c, 0x6f, 0xf9, 0x04, 0x3f, 0x42, 0x0f, 0x68, 0xeb, 0xd0, 0x2a, 0x1d, + 0x52, 0x5d, 0x00, 0x09, 0x2b, 0x4c, 0xb7, 0x58, 0x98, 0xbb, 0x90, 0xbe, + 0x59, 0x97, 0x61, 0x99, 0xfa, 0x08, 0xc2, 0xb7, 0x4f, 0x7e, 0x84, 0x4e, + 0xc2, 0x0f, 0xa7, 0x57, 0xfd, 0xc7, 0x67, 0xa9, 0x1c, 0x83, 0xaf, 0xfd, + 0xc4, 0xd4, 0xbe, 0xf6, 0x06, 0x0e, 0xbe, 0xe2, 0x42, 0xce, 0xbf, 0xff, + 0x79, 0x40, 0x46, 0x07, 0xb9, 0xad, 0xe5, 0x1d, 0x3a, 0xb8, 0x8b, 0x45, + 0x9f, 0x09, 0x05, 0xcf, 0x23, 0xaf, 0xff, 0xff, 0xe1, 0x76, 0x7d, 0x9d, + 0x1c, 0xf0, 0x3f, 0x5b, 0xc9, 0xc3, 0x02, 0xfc, 0x79, 0x1d, 0x7f, 0xb3, + 0xbd, 0x07, 0x9c, 0x4e, 0xbe, 0x5a, 0x4d, 0xa3, 0xac, 0x81, 0x47, 0x6c, + 0xc2, 0xbc, 0x84, 0x2a, 0xcc, 0x6f, 0xdc, 0x9b, 0x66, 0x04, 0xeb, 0xff, + 0x63, 0x3b, 0x5c, 0xcd, 0xa1, 0x03, 0x27, 0x54, 0x27, 0xa7, 0xd8, 0xc7, + 0x1d, 0x20, 0x4a, 0xaf, 0xff, 0xff, 0xbf, 0xd6, 0x60, 0xa9, 0xf7, 0x83, + 0x19, 0xd6, 0x34, 0x39, 0x3a, 0xf1, 0x67, 0x5f, 0xbe, 0xc0, 0xfd, 0x59, + 0xd5, 0x88, 0xa9, 0xf3, 0xfd, 0xfb, 0x63, 0xf6, 0x3e, 0x9d, 0x58, 0x79, + 0x88, 0x45, 0x7b, 0x51, 0x39, 0xd7, 0xfd, 0x18, 0xde, 0xa6, 0xc7, 0xe1, + 0xd7, 0x67, 0x4e, 0xa1, 0x3c, 0xdd, 0xb3, 0x8a, 0x92, 0x2b, 0x74, 0x41, + 0xe6, 0x9b, 0xdd, 0x03, 0x27, 0x5e, 0xfc, 0x0d, 0x3a, 0xf7, 0xb3, 0xe9, + 0xd7, 0xf4, 0x6f, 0xaf, 0x9c, 0x83, 0xaf, 0x04, 0x0d, 0x3a, 0xf8, 0x23, + 0x12, 0x3a, 0x90, 0xde, 0x38, 0xe5, 0x05, 0x1c, 0x3b, 0x8e, 0xa0, 0xea, + 0xc7, 0x7a, 0xd7, 0x76, 0x34, 0xeb, 0xfb, 0x89, 0xb3, 0x07, 0x47, 0x5f, + 0xdb, 0xfb, 0x3a, 0x05, 0x73, 0xaf, 0xee, 0x67, 0x7a, 0x0f, 0x1d, 0x7e, + 0xe8, 0xc6, 0x70, 0xcb, 0xfb, 0x39, 0x38, 0x1c, 0x26, 0x88, 0x35, 0x83, + 0x4b, 0x6e, 0x4e, 0x89, 0xd9, 0x29, 0x54, 0x23, 0xe1, 0x21, 0x9d, 0x7e, + 0x76, 0xa2, 0xe0, 0xeb, 0xfa, 0x5d, 0x17, 0xdf, 0xc7, 0x5b, 0x1a, 0x7a, + 0x42, 0x4b, 0x7e, 0x8f, 0x7c, 0x5b, 0x27, 0x5f, 0xe9, 0x22, 0xe3, 0xbf, + 0x42, 0x75, 0xff, 0xe8, 0xc1, 0xdf, 0xd9, 0xc4, 0x9d, 0xd6, 0x75, 0xf9, + 0xd9, 0xf6, 0x77, 0x47, 0xf9, 0xe3, 0x4a, 0x56, 0xd5, 0x5e, 0xc0, 0xac, + 0xa3, 0x25, 0xc7, 0x8e, 0x13, 0x0c, 0x29, 0xaf, 0x6b, 0x24, 0x75, 0xf9, + 0x37, 0x92, 0x09, 0xd7, 0x93, 0xb8, 0x75, 0xd0, 0xbc, 0x3c, 0x06, 0x93, + 0x5f, 0x07, 0x5d, 0x83, 0xaf, 0xc3, 0xc6, 0x5e, 0x73, 0xab, 0x0f, 0x25, + 0xc8, 0x6e, 0x00, 0x9d, 0x50, 0x98, 0x2a, 0x2d, 0xf1, 0xd7, 0x44, 0x17, + 0xbb, 0x82, 0x75, 0xfe, 0x9a, 0x27, 0x5b, 0xcd, 0x07, 0x5f, 0xff, 0x3a, + 0x9e, 0x8e, 0x7f, 0xc8, 0xf0, 0xbf, 0xe7, 0x5f, 0xff, 0xc2, 0xea, 0x7c, + 0xfa, 0x2f, 0xed, 0x26, 0xfd, 0x46, 0x4e, 0xac, 0x47, 0xeb, 0x8d, 0x09, + 0xa0, 0x14, 0x2e, 0xd6, 0xc3, 0xaf, 0x90, 0x5c, 0x27, 0x5f, 0xf9, 0x79, + 0xed, 0x7d, 0xd3, 0xcb, 0x0e, 0xbf, 0x6a, 0x39, 0xe8, 0x39, 0x83, 0x7f, + 0x41, 0x44, 0xae, 0x97, 0xaf, 0xdf, 0x66, 0x77, 0xe1, 0xd7, 0xdd, 0xc4, + 0xd8, 0x75, 0xfd, 0xa4, 0xe6, 0x03, 0x87, 0x5f, 0xff, 0xe8, 0x9b, 0xe2, + 0x34, 0x1c, 0xd0, 0x3e, 0x2d, 0x3d, 0xd4, 0x3a, 0xb1, 0x3a, 0xc4, 0x85, + 0x6a, 0xc8, 0xfa, 0x53, 0xe2, 0x2d, 0xa2, 0xcb, 0x96, 0xa8, 0x34, 0x5f, + 0x97, 0xda, 0xe6, 0x61, 0xd7, 0xff, 0x4b, 0xc0, 0x94, 0x97, 0xef, 0x42, + 0xce, 0xbf, 0xde, 0xd4, 0x4f, 0x9a, 0x09, 0xd7, 0x77, 0x0e, 0xbf, 0xfe, + 0xec, 0x07, 0x1b, 0xf3, 0x07, 0x03, 0xd8, 0x3a, 0xff, 0xe4, 0xc1, 0xcc, + 0xd7, 0xc9, 0x69, 0x67, 0x5f, 0xf9, 0xe3, 0x79, 0x7c, 0xd6, 0xe1, 0x83, + 0xa8, 0x29, 0xbf, 0xee, 0x40, 0x88, 0xaa, 0xe6, 0x73, 0x0a, 0xe9, 0x3b, + 0xc8, 0x77, 0x94, 0x8e, 0x1d, 0x7f, 0x06, 0x3f, 0xe6, 0x6e, 0x75, 0x30, + 0x79, 0x4b, 0x1c, 0xbf, 0xd0, 0xbc, 0x4e, 0x4d, 0x23, 0xae, 0x49, 0x8e, + 0xbf, 0xfd, 0xe8, 0xe8, 0xbc, 0xf1, 0xce, 0x3c, 0x8e, 0xbd, 0xe4, 0x9c, + 0xeb, 0xf7, 0xef, 0xbc, 0x4c, 0x75, 0xe1, 0x86, 0x9d, 0x7f, 0xf0, 0x52, + 0x6e, 0xc7, 0x37, 0x94, 0x70, 0xeb, 0xff, 0x85, 0xf7, 0xd6, 0xb3, 0x81, + 0xee, 0x1d, 0x7f, 0xfa, 0x1b, 0xf3, 0x98, 0x80, 0x54, 0xe6, 0xd6, 0x1d, + 0x48, 0x89, 0x31, 0x43, 0xaf, 0x89, 0xdb, 0x20, 0xb2, 0xd2, 0x1c, 0x70, + 0x4a, 0x74, 0x35, 0xb5, 0x0d, 0x8b, 0x41, 0xd7, 0xba, 0x9e, 0x3a, 0xdb, + 0x30, 0xd5, 0x7d, 0x0f, 0xa8, 0x5d, 0x82, 0x0a, 0xf6, 0x47, 0x4c, 0x90, + 0xb3, 0xe9, 0x1b, 0xc7, 0xd1, 0xfc, 0x25, 0xaf, 0xfb, 0x06, 0x43, 0x8b, + 0x86, 0x9d, 0x7e, 0xea, 0x6c, 0xc0, 0x9d, 0x7f, 0xe0, 0xc0, 0xe0, 0x82, + 0x59, 0xa3, 0xaf, 0xce, 0xb4, 0xda, 0xc3, 0xaf, 0x7a, 0x37, 0x3a, 0xb0, + 0xf1, 0x1c, 0xa2, 0xf4, 0x24, 0xc7, 0x5e, 0x15, 0x67, 0x68, 0xeb, 0xf6, + 0x4e, 0xb8, 0xd1, 0xd7, 0xff, 0xfe, 0x8e, 0xa2, 0xd8, 0x9a, 0x4f, 0xcf, + 0xbd, 0x4d, 0xf4, 0xd4, 0x9c, 0xea, 0x0a, 0x7a, 0x4a, 0x1a, 0xa1, 0x44, + 0xcf, 0xfd, 0x20, 0x11, 0xbd, 0x11, 0xed, 0x13, 0xdf, 0xcf, 0xc8, 0xef, + 0xd0, 0x9d, 0x7d, 0x09, 0x3c, 0x1d, 0x7c, 0xcb, 0xe6, 0x8e, 0xbf, 0xe9, + 0x2d, 0xe5, 0xed, 0x42, 0x87, 0x54, 0x1e, 0xd3, 0x90, 0xde, 0xd2, 0x09, + 0xd7, 0xe1, 0x6f, 0xcd, 0x6e, 0x75, 0x61, 0xe2, 0x38, 0xd5, 0x3a, 0x65, + 0x9f, 0x97, 0x0b, 0xd0, 0x19, 0x2e, 0x9e, 0x47, 0x5e, 0x4e, 0xa1, 0xd5, + 0xb9, 0xb1, 0xf0, 0xbd, 0xf7, 0xd0, 0x3e, 0x8e, 0xbf, 0xd2, 0x00, 0xcf, + 0xa4, 0xdc, 0xeb, 0xef, 0xff, 0xcd, 0xce, 0xbf, 0xb6, 0xbd, 0x8e, 0x2d, + 0x3a, 0xff, 0x80, 0xf2, 0x0e, 0x67, 0xfa, 0x3a, 0xff, 0x7e, 0x9b, 0xef, + 0x2c, 0xf1, 0xd5, 0xd3, 0xed, 0xd1, 0xc5, 0xfb, 0x7d, 0x2d, 0x15, 0xce, + 0xbf, 0xff, 0x66, 0xbe, 0x75, 0xd3, 0xdf, 0x80, 0x45, 0xe4, 0x75, 0x42, + 0x20, 0x04, 0xae, 0xfe, 0x79, 0xff, 0x71, 0x09, 0xd5, 0x32, 0x7c, 0x7c, + 0x34, 0xe9, 0x27, 0xa1, 0x37, 0xb2, 0x14, 0x5b, 0x64, 0x37, 0xfd, 0xdf, + 0xb0, 0xdd, 0xbc, 0xe4, 0x1d, 0x50, 0xaa, 0xab, 0x25, 0x03, 0x3b, 0x45, + 0xd3, 0x00, 0xeb, 0x2c, 0xea, 0xdc, 0xd3, 0xaa, 0x45, 0xef, 0xfe, 0x8e, + 0x66, 0xc7, 0x97, 0xf9, 0x81, 0x3a, 0xfe, 0x7d, 0xe4, 0x30, 0x13, 0xaf, + 0xfa, 0x37, 0x92, 0x0a, 0xdf, 0xc7, 0x53, 0x9f, 0x18, 0x96, 0x5f, 0x9e, + 0x59, 0x3c, 0x1d, 0x7f, 0xf4, 0x6b, 0x58, 0xbf, 0x0c, 0x2f, 0x47, 0x5f, + 0xfc, 0x91, 0xa1, 0x79, 0x7c, 0xd6, 0x70, 0xeb, 0xff, 0xfc, 0x9a, 0x9f, + 0x19, 0xc1, 0x06, 0xd4, 0x31, 0x82, 0xfc, 0x3a, 0xff, 0x6f, 0x2d, 0x4d, + 0x28, 0x9c, 0xea, 0x0a, 0x68, 0x6d, 0x26, 0x14, 0x2f, 0x21, 0x81, 0x8a, + 0xff, 0xff, 0xdd, 0x4d, 0xfd, 0x9b, 0xfb, 0x9c, 0x8f, 0x7f, 0xf4, 0x65, + 0xdc, 0x3a, 0xf8, 0x21, 0x71, 0x3a, 0xff, 0xd2, 0x81, 0xf7, 0x13, 0x66, + 0x04, 0xeb, 0xff, 0x3f, 0x5a, 0x8f, 0xf3, 0x4f, 0xd3, 0xaf, 0xff, 0xda, + 0x1f, 0x9d, 0x74, 0xf7, 0xe0, 0x11, 0x79, 0x1d, 0x7f, 0xba, 0x8a, 0x6d, + 0x83, 0x8a, 0x1d, 0x7f, 0xd0, 0xca, 0xfb, 0x08, 0x33, 0x9d, 0x7f, 0xfc, + 0x39, 0xac, 0x5c, 0x37, 0x3c, 0x9c, 0xc3, 0xad, 0x8d, 0x45, 0xdf, 0x8e, + 0x36, 0x1c, 0x5f, 0xd3, 0xe7, 0x11, 0xb0, 0x75, 0xf0, 0x86, 0x16, 0x75, + 0xfb, 0x66, 0x08, 0x1c, 0xeb, 0xf9, 0xff, 0xc0, 0xbc, 0x8e, 0xa8, 0x3f, + 0x3c, 0x20, 0x42, 0x7a, 0x44, 0x65, 0xf6, 0x13, 0xf5, 0x0b, 0xb7, 0xf3, + 0x93, 0x06, 0x14, 0xf9, 0x1b, 0x1b, 0x52, 0x91, 0xc2, 0x62, 0x0e, 0x9f, + 0x7e, 0x7c, 0x31, 0x88, 0x7a, 0x30, 0x2b, 0xff, 0xb0, 0x7f, 0xcc, 0xe6, + 0xbd, 0x18, 0x75, 0xff, 0x6f, 0xec, 0xe2, 0x4e, 0xeb, 0x3a, 0xd9, 0xf9, + 0xfd, 0x0a, 0x0d, 0xe5, 0x4c, 0x90, 0xeb, 0xe8, 0x17, 0x91, 0xd7, 0xec, + 0x57, 0x71, 0xff, 0xe1, 0xbe, 0xe0, 0xfd, 0xfd, 0xb3, 0xa9, 0x1c, 0xd1, + 0xd7, 0xff, 0xe8, 0x19, 0x67, 0x51, 0x61, 0xc9, 0xa3, 0x38, 0x75, 0xf3, + 0x7a, 0x93, 0x1d, 0x7f, 0xfe, 0x1c, 0x51, 0x44, 0x0f, 0x52, 0x6e, 0xa6, + 0xfe, 0x3a, 0xa0, 0xfe, 0x70, 0x8a, 0xf3, 0x5f, 0x87, 0x5f, 0xb4, 0xd8, + 0xe2, 0x87, 0x57, 0x4f, 0x0f, 0xf1, 0xbb, 0xfd, 0x92, 0xc4, 0x0f, 0x50, + 0xeb, 0xef, 0x49, 0x7d, 0x3a, 0xf9, 0x14, 0x46, 0x4e, 0xac, 0x3c, 0x41, + 0x22, 0xbb, 0xe6, 0x1d, 0x7d, 0xa1, 0x85, 0x9d, 0x50, 0x6d, 0xf7, 0x17, + 0xbe, 0xce, 0xc9, 0x67, 0x54, 0x2b, 0x33, 0x93, 0x2e, 0x21, 0x28, 0x5d, + 0xd8, 0x65, 0xbb, 0x18, 0x91, 0xe9, 0xd0, 0x0a, 0xfb, 0x64, 0x37, 0x82, + 0xb6, 0x9d, 0x6e, 0x9d, 0x76, 0xa4, 0x75, 0x7e, 0x69, 0x80, 0x21, 0x7f, + 0x4f, 0x34, 0x95, 0x5c, 0x9c, 0xeb, 0xcf, 0x9c, 0x3a, 0xf0, 0xe7, 0x8e, + 0xae, 0x9b, 0x41, 0x1a, 0xbb, 0xc2, 0x75, 0xe8, 0xdf, 0x47, 0x5f, 0x20, + 0xcb, 0x0e, 0xbd, 0x3b, 0x89, 0xd4, 0x13, 0xd6, 0x58, 0xe7, 0x87, 0xef, + 0xd9, 0xee, 0xa7, 0x8e, 0xbf, 0x3e, 0xf9, 0xbf, 0x8e, 0xb2, 0x9d, 0x3c, + 0xef, 0x13, 0x5c, 0x9c, 0x3a, 0xfe, 0x9f, 0xe4, 0xee, 0xfd, 0x3a, 0x95, + 0x94, 0xf7, 0xe1, 0xa6, 0x44, 0x18, 0xd6, 0x8f, 0xbd, 0x29, 0x71, 0x5b, + 0xfe, 0xc0, 0x85, 0x37, 0xcd, 0xfc, 0x75, 0xf3, 0x46, 0x24, 0x75, 0x74, + 0xf6, 0x5c, 0xe6, 0xff, 0x46, 0x7a, 0x3a, 0xe1, 0x3a, 0xa7, 0x3d, 0x10, + 0x90, 0xdf, 0xfc, 0x18, 0x0f, 0x23, 0xc8, 0xd4, 0x09, 0xd7, 0xd3, 0x46, + 0xd4, 0x8e, 0xbf, 0xbc, 0xd0, 0x85, 0x7c, 0x3a, 0xff, 0xa6, 0xd6, 0xc7, + 0x19, 0xc0, 0x13, 0xaf, 0xb3, 0xd8, 0xb3, 0xae, 0x15, 0x0e, 0xb6, 0x9c, + 0xdb, 0x00, 0x82, 0xfe, 0xe8, 0x27, 0x9b, 0xa8, 0x75, 0xf0, 0x8e, 0x78, + 0xea, 0x84, 0xe7, 0x82, 0x47, 0x88, 0x4a, 0x12, 0xa1, 0x74, 0xce, 0x5d, + 0x26, 0xf1, 0x7d, 0xfd, 0xf2, 0x68, 0xf0, 0xec, 0x3a, 0xff, 0xf0, 0xc6, + 0xce, 0x47, 0x31, 0x3b, 0x01, 0x3a, 0xf0, 0xba, 0xce, 0xa9, 0x22, 0x4f, + 0x0c, 0x51, 0x22, 0xcc, 0x2b, 0x2e, 0xe9, 0xf9, 0x5b, 0x3c, 0x56, 0x83, + 0x8a, 0xd4, 0x6e, 0x25, 0x2d, 0x4f, 0x0e, 0xb9, 0x43, 0x64, 0x33, 0x88, + 0x39, 0x3b, 0x6a, 0xa4, 0x37, 0x1b, 0x2a, 0xfb, 0x78, 0xf8, 0xd2, 0x31, + 0x19, 0xa5, 0x83, 0xf2, 0x36, 0xb5, 0xc6, 0x73, 0xd9, 0xf6, 0x87, 0x94, + 0x99, 0xfc, 0x74, 0x2a, 0x96, 0xe1, 0x95, 0x99, 0xa9, 0xe1, 0xcf, 0x4e, + 0x2f, 0x02, 0x12, 0x4c, 0xa1, 0x6d, 0xca, 0x01, 0xfb, 0x2a, 0xbb, 0x6a, + 0x30, 0x4a, 0x61, 0xde, 0x82, 0x76, 0xdd, 0x67, 0x5f, 0xfe, 0x61, 0x6f, + 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x6c, 0xbf, 0xcc, 0x67, 0x1a, 0xee, + 0xd3, 0x45, 0x5b, 0x7f, 0xa5, 0x20, 0x78, 0x62, 0x47, 0x5f, 0x67, 0x5f, + 0xc7, 0x59, 0x51, 0x87, 0xa4, 0x26, 0x57, 0xfb, 0x98, 0xd8, 0xff, 0xea, + 0xce, 0xbf, 0xe8, 0xec, 0x4f, 0xc8, 0xc0, 0x9d, 0x5c, 0x3e, 0xce, 0x9a, + 0xdf, 0xa3, 0x8b, 0xe8, 0x4e, 0xbc, 0x1c, 0x13, 0xaf, 0x3b, 0xb4, 0xd1, + 0x5a, 0x5f, 0x94, 0xdf, 0x40, 0xdc, 0xea, 0x69, 0xe9, 0x21, 0x3d, 0xff, + 0xe4, 0xf4, 0xa1, 0xbd, 0x4f, 0x69, 0xf7, 0x3a, 0xb8, 0x7d, 0x5b, 0x08, + 0x6f, 0xff, 0x75, 0x17, 0x0d, 0xc5, 0xe0, 0xfb, 0x6c, 0xeb, 0xff, 0xe6, + 0xc7, 0x33, 0xf7, 0x5b, 0xca, 0x11, 0xa7, 0x5f, 0xff, 0x4b, 0x58, 0x30, + 0xb7, 0xcf, 0x7a, 0x16, 0x75, 0xde, 0xf4, 0x22, 0x65, 0xd3, 0x6f, 0xff, + 0xff, 0x46, 0xc4, 0xf6, 0xb1, 0x46, 0xf5, 0x3d, 0x93, 0x0c, 0x2e, 0x7c, + 0x64, 0xeb, 0xfd, 0x1e, 0x7e, 0xfc, 0x0c, 0x1d, 0x7d, 0x2f, 0x24, 0xe7, + 0x5f, 0xbe, 0xf8, 0x63, 0xf3, 0xab, 0x73, 0xcb, 0xd8, 0x45, 0x7f, 0x9e, + 0x5e, 0x49, 0xfa, 0x87, 0x54, 0x1e, 0xba, 0x12, 0xdf, 0xb3, 0xa9, 0x8b, + 0x3a, 0xff, 0xe1, 0x74, 0x6f, 0x5c, 0x13, 0xf1, 0x0e, 0xa9, 0xcf, 0x9f, + 0xa4, 0xb7, 0xfa, 0x51, 0xc9, 0xe3, 0x93, 0x9d, 0x7b, 0x39, 0xf9, 0xd7, + 0xe9, 0xb0, 0x2b, 0x57, 0x3a, 0xfe, 0x18, 0x67, 0x79, 0x68, 0xea, 0x43, + 0xf5, 0x98, 0x73, 0x68, 0xae, 0xa1, 0x1b, 0x79, 0x0a, 0x9b, 0xff, 0xff, + 0xfb, 0x11, 0xb9, 0xe8, 0x1f, 0x6b, 0xe4, 0x20, 0x71, 0x7f, 0x39, 0x09, + 0x27, 0xd1, 0xd7, 0xf6, 0x79, 0xc7, 0xf0, 0x1d, 0x7f, 0x77, 0xe2, 0x4e, + 0xe2, 0x75, 0x48, 0xf6, 0xb0, 0xb2, 0xcc, 0x2a, 0x97, 0xb9, 0x62, 0x12, + 0xd3, 0x91, 0x04, 0x9f, 0x21, 0xac, 0xd2, 0x44, 0x87, 0x1f, 0x0b, 0x56, + 0xf5, 0xd8, 0x6a, 0xbc, 0x21, 0xc6, 0x1f, 0xda, 0x26, 0xf4, 0x38, 0x6f, + 0xf3, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x60, 0x5f, 0xb8, 0xd7, 0x76, 0x9a, + 0x27, 0x5b, 0xff, 0xfd, 0xd8, 0x9c, 0x38, 0xb6, 0x35, 0xac, 0xea, 0x68, + 0x13, 0x9d, 0x7e, 0x61, 0x6f, 0x26, 0x31, 0x12, 0xd3, 0x19, 0xdf, 0xe9, + 0x69, 0x85, 0x14, 0x85, 0x9d, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xb6, 0x6f, + 0xff, 0xf3, 0xc9, 0x8d, 0x42, 0x60, 0x53, 0x35, 0x9e, 0x18, 0x3a, 0xff, + 0xdf, 0xc6, 0x98, 0xea, 0x35, 0xf8, 0x75, 0xff, 0x44, 0xa3, 0x93, 0xc7, + 0x27, 0x3a, 0xcc, 0x62, 0x60, 0xeb, 0x33, 0x75, 0xc1, 0x3f, 0xbf, 0xff, + 0x3f, 0xff, 0x83, 0x4c, 0x67, 0x1f, 0x5d, 0x79, 0x1d, 0x7c, 0xd7, 0x76, + 0x9a, 0x2e, 0x6b, 0x2c, 0xea, 0xe1, 0xbd, 0x64, 0xb6, 0xff, 0x70, 0x73, + 0x7f, 0xd2, 0x47, 0x5d, 0x32, 0xce, 0xa3, 0xac, 0xc6, 0x1f, 0xb2, 0x11, + 0x32, 0x67, 0xb6, 0x2f, 0x7e, 0xe3, 0x5d, 0xda, 0x68, 0xbb, 0xef, 0xf4, + 0x98, 0xd7, 0x38, 0x8c, 0x9d, 0x66, 0x30, 0xfa, 0x1c, 0xce, 0xf9, 0x85, + 0x03, 0xf9, 0xd5, 0x0f, 0x95, 0x6f, 0x96, 0xf4, 0xc1, 0xa6, 0xbb, 0xab, + 0xa4, 0xfb, 0xb7, 0x21, 0xd8, 0xb8, 0x6a, 0xba, 0x17, 0xf1, 0x9e, 0x8a, + 0x16, 0xa3, 0x0a, 0xf4, 0x2b, 0x7e, 0x93, 0xdf, 0xf9, 0x97, 0x19, 0xf4, + 0x83, 0xbc, 0x8e, 0xbf, 0xfb, 0x27, 0xc6, 0x7b, 0x9a, 0xc4, 0x13, 0xae, + 0x46, 0x3a, 0x88, 0x11, 0x3f, 0xbf, 0x6b, 0x4b, 0x79, 0x1d, 0x7f, 0xff, + 0xff, 0xee, 0xa7, 0x52, 0x07, 0xc2, 0xea, 0x67, 0x81, 0xe4, 0xf6, 0xba, + 0x9c, 0x89, 0xdf, 0x8d, 0x3a, 0xed, 0x41, 0xd7, 0xff, 0x6e, 0xd0, 0x3e, + 0xfe, 0xcc, 0x15, 0x0e, 0xbc, 0x2e, 0xc4, 0x26, 0x30, 0xd2, 0x7d, 0x42, + 0x5f, 0xc2, 0xb7, 0x80, 0xeb, 0x3a, 0xfd, 0x9b, 0x5e, 0x85, 0x0e, 0xb6, + 0xd1, 0xd5, 0x39, 0xbd, 0xc2, 0xaa, 0xe1, 0xfc, 0x8a, 0xc5, 0xff, 0xb4, + 0xea, 0x75, 0x20, 0x41, 0x07, 0x5f, 0xfb, 0xaf, 0xe7, 0xee, 0xf2, 0xcf, + 0x1d, 0x58, 0x7f, 0x48, 0x79, 0x73, 0xfe, 0x75, 0xff, 0xff, 0xe1, 0x76, + 0x47, 0x3d, 0xec, 0x9e, 0x05, 0xd4, 0xd2, 0xe3, 0x04, 0x27, 0x56, 0x22, + 0x2b, 0x82, 0xd7, 0xfb, 0xb8, 0x14, 0xd9, 0xcc, 0x3a, 0xf3, 0xbb, 0x4d, + 0x12, 0xbd, 0xfe, 0x51, 0xc7, 0xff, 0x67, 0x4e, 0xa6, 0x9e, 0xd2, 0x13, + 0xdf, 0xfe, 0xf7, 0x72, 0x4d, 0xea, 0x06, 0x07, 0xc7, 0x54, 0x91, 0xed, + 0xc8, 0x46, 0x89, 0x0d, 0xd2, 0x9c, 0xeb, 0xff, 0x0b, 0xb2, 0x1e, 0xc4, + 0xf8, 0xc9, 0xd7, 0xff, 0xec, 0x4f, 0xf1, 0x69, 0xed, 0x42, 0xdf, 0x7f, + 0x1d, 0x7f, 0xd0, 0xbf, 0x64, 0xd2, 0x4f, 0x1d, 0x52, 0x44, 0x67, 0x95, + 0x2f, 0x80, 0xfc, 0x91, 0xd7, 0xfd, 0x0d, 0x18, 0x9f, 0xf7, 0xf1, 0xd7, + 0xff, 0xf9, 0x3c, 0xeb, 0x71, 0xff, 0xac, 0xb8, 0xce, 0xd4, 0x9c, 0xea, + 0x0a, 0x2e, 0x90, 0x85, 0xce, 0x2f, 0xf8, 0x1f, 0xad, 0xe5, 0xae, 0x04, + 0xeb, 0xff, 0xfd, 0x88, 0x3e, 0xc1, 0xf8, 0x2e, 0x18, 0x19, 0xe3, 0x87, + 0x5b, 0x3c, 0x89, 0x7d, 0x87, 0x57, 0xfd, 0xbf, 0xf9, 0xcc, 0xcf, 0x68, + 0xea, 0x0a, 0xad, 0x0c, 0x86, 0x5f, 0x61, 0xba, 0x30, 0xc5, 0xfa, 0x55, + 0x7f, 0xef, 0x3c, 0xb5, 0xd8, 0xe7, 0xd0, 0x9d, 0x7f, 0xf7, 0x93, 0x62, + 0x7a, 0x69, 0x40, 0xf8, 0xeb, 0xff, 0xcf, 0x92, 0xee, 0x20, 0xe7, 0xfb, + 0x78, 0x75, 0xe7, 0x93, 0x10, 0xbd, 0x43, 0x28, 0x4d, 0x86, 0x15, 0x59, + 0x18, 0xc2, 0xcd, 0x35, 0x2b, 0x9f, 0xcb, 0x7f, 0x50, 0x36, 0x91, 0x6f, + 0xff, 0x67, 0x58, 0x1c, 0x0a, 0x0f, 0xb3, 0xa7, 0x5e, 0xf4, 0x04, 0xab, + 0xff, 0xdd, 0x74, 0xf4, 0x49, 0x39, 0x38, 0x3f, 0x2a, 0xff, 0x3b, 0x58, + 0x0f, 0x15, 0x2c, 0x41, 0xf2, 0xe8, 0x6e, 0xcc, 0x05, 0x94, 0xb8, 0xd8, + 0xd1, 0x97, 0x3e, 0xdb, 0xe8, 0x56, 0xec, 0x85, 0x65, 0xff, 0xe6, 0x16, + 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x26, 0x1b, 0xff, 0xfb, 0x36, 0x38, + 0x7b, 0x0c, 0x7b, 0xb8, 0x10, 0x7b, 0x47, 0x5f, 0xfe, 0xe3, 0xfe, 0xc2, + 0x9e, 0x93, 0x31, 0xa9, 0x1d, 0x76, 0x30, 0x28, 0xab, 0xfa, 0xbb, 0x7f, + 0xf2, 0xa3, 0x37, 0x90, 0x1f, 0xc3, 0x12, 0x3a, 0xfd, 0x8b, 0xf9, 0xba, + 0xb9, 0xd7, 0xf4, 0x2f, 0x3f, 0x8d, 0x87, 0x50, 0x4f, 0x6f, 0xa5, 0xb7, + 0xfb, 0x98, 0xd8, 0xff, 0xea, 0xce, 0xbf, 0x76, 0x02, 0x8a, 0x1d, 0x48, + 0x7f, 0xdc, 0x22, 0xda, 0x35, 0xbf, 0xd0, 0xf3, 0xf9, 0x47, 0xe1, 0xd7, + 0xe7, 0xe4, 0x9d, 0x67, 0x50, 0x9e, 0xc8, 0x0c, 0xef, 0xff, 0xc9, 0xce, + 0xbf, 0xc0, 0xe4, 0xbb, 0x1b, 0x03, 0x07, 0x5f, 0xf3, 0x3f, 0x7b, 0x0d, + 0xea, 0x4c, 0x75, 0xf0, 0x17, 0x81, 0x3a, 0xd9, 0xb9, 0xee, 0xed, 0x1e, + 0x57, 0x51, 0xbe, 0x30, 0xb4, 0xbf, 0x97, 0x18, 0x3e, 0xdb, 0x3a, 0xda, + 0x3a, 0xfd, 0x18, 0x3e, 0xdb, 0x3a, 0xfe, 0xea, 0x7b, 0x4f, 0xbf, 0xc3, + 0xe6, 0x98, 0xb9, 0x62, 0x17, 0xfa, 0x5e, 0x85, 0xec, 0xfe, 0x47, 0x5f, + 0xff, 0xe6, 0x76, 0xbd, 0x9d, 0xf8, 0x39, 0x3a, 0x60, 0xef, 0x2d, 0x1d, + 0x7e, 0x67, 0xd9, 0xd6, 0x9d, 0x61, 0xc4, 0x47, 0x3b, 0x35, 0xff, 0xef, + 0x0b, 0xff, 0xdc, 0x40, 0x83, 0xda, 0x3a, 0xff, 0xa2, 0x7f, 0xb2, 0xe8, + 0x1e, 0x73, 0xaa, 0x11, 0x0b, 0xc4, 0x9b, 0xff, 0xb3, 0x79, 0x7c, 0xeb, + 0xb6, 0x04, 0x27, 0x5f, 0xdb, 0x3e, 0xf8, 0x63, 0xf3, 0xaf, 0xff, 0x47, + 0xbf, 0x89, 0x66, 0xfe, 0x9c, 0x0c, 0x9d, 0x50, 0x7f, 0xc8, 0x63, 0x7f, + 0x3f, 0xfc, 0xe2, 0x70, 0xeb, 0xde, 0xf9, 0x87, 0x57, 0xe7, 0x95, 0xf4, + 0xb6, 0xfe, 0xd2, 0x28, 0xb7, 0xf1, 0xd7, 0xff, 0xfe, 0xe6, 0x6c, 0x81, + 0xf7, 0xcf, 0xa3, 0x1d, 0x74, 0xf4, 0x7b, 0x47, 0x5f, 0xc3, 0x9a, 0xf8, + 0xd5, 0x51, 0xd5, 0xba, 0x33, 0x78, 0x5b, 0xb1, 0xba, 0xfb, 0xe6, 0xcd, + 0xa9, 0xce, 0xac, 0x3d, 0xd5, 0x0c, 0xec, 0xae, 0x75, 0xde, 0xc3, 0xaf, + 0xff, 0x2a, 0x46, 0x16, 0xe9, 0xd7, 0xf7, 0x60, 0xea, 0x83, 0xdf, 0x00, + 0xad, 0xfe, 0xea, 0x4c, 0xed, 0xd4, 0x8e, 0xbf, 0xd0, 0x3e, 0x75, 0xa7, + 0x8e, 0xbf, 0xec, 0x4c, 0x58, 0xe4, 0xee, 0x75, 0xfa, 0x3d, 0xaf, 0xc0, + 0x75, 0x2b, 0x29, 0xa9, 0xe3, 0x93, 0x48, 0x7a, 0x66, 0x26, 0x1e, 0x35, + 0xbf, 0xff, 0x74, 0x73, 0xdd, 0x4c, 0xdf, 0xd9, 0xb2, 0x34, 0x75, 0xff, + 0xce, 0x3d, 0x84, 0x0a, 0x6b, 0x24, 0x75, 0xe8, 0xff, 0xe9, 0xd5, 0x88, + 0xb3, 0x75, 0x51, 0x40, 0xbd, 0xf4, 0x38, 0x75, 0xe5, 0x4e, 0x95, 0x47, + 0x53, 0x9e, 0x0e, 0x87, 0x6f, 0xf0, 0xbb, 0x31, 0xec, 0x9c, 0xeb, 0x30, + 0xaa, 0x65, 0x6e, 0xc4, 0x64, 0x01, 0x84, 0x56, 0x46, 0x00, 0xd8, 0x46, + 0xee, 0xab, 0x34, 0x31, 0x39, 0x0a, 0xb5, 0x91, 0x76, 0x18, 0x7f, 0xb5, + 0x0c, 0x69, 0xfa, 0x8d, 0xd7, 0xd1, 0x87, 0x01, 0xbb, 0x6c, 0x86, 0xff, + 0xfb, 0x89, 0xbc, 0xb4, 0x9e, 0xec, 0x73, 0xd0, 0x75, 0xfb, 0x8d, 0x77, + 0x69, 0xa2, 0xae, 0xbd, 0xc8, 0x59, 0xd7, 0xfd, 0x26, 0x33, 0x8d, 0x77, + 0x69, 0xa2, 0x3c, 0xbf, 0xe8, 0x94, 0x72, 0x78, 0xe4, 0xe7, 0x5f, 0xfa, + 0x3c, 0x80, 0x54, 0xe4, 0xa7, 0x98, 0xeb, 0x30, 0x14, 0xd7, 0xb1, 0x3f, + 0x86, 0x6e, 0x36, 0x28, 0xba, 0x39, 0xbf, 0x71, 0xae, 0xed, 0x34, 0x58, + 0x37, 0x94, 0x89, 0xce, 0xbf, 0xff, 0x84, 0x0f, 0x3a, 0xf3, 0x6c, 0x1c, + 0xce, 0x4b, 0xec, 0x8e, 0xbf, 0x60, 0xe7, 0xb4, 0x75, 0xfe, 0xe3, 0xaf, + 0xef, 0x1f, 0x73, 0xac, 0xc6, 0x26, 0x14, 0xa1, 0x9b, 0x47, 0x5d, 0x83, + 0xe9, 0x2d, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x2c, 0xab, 0xf7, 0x1a, + 0xee, 0xd3, 0x45, 0xa7, 0x7f, 0xce, 0x1e, 0xbc, 0xdd, 0x45, 0x9d, 0x66, + 0x30, 0xfa, 0xd6, 0x67, 0x7e, 0x56, 0x8a, 0xbd, 0x59, 0x56, 0x55, 0xb3, + 0xaf, 0xf9, 0x55, 0xd4, 0x64, 0x2e, 0xed, 0x3a, 0xfc, 0xad, 0x15, 0x1a, + 0xc8, 0x3a, 0xff, 0x7d, 0x5e, 0x7b, 0x49, 0xa3, 0xac, 0x87, 0x52, 0xa8, + 0xf0, 0xf6, 0xcd, 0x2f, 0xff, 0xe4, 0xeb, 0x8f, 0xa5, 0x9c, 0xc8, 0x11, + 0xcf, 0x1d, 0x7e, 0xd8, 0xe1, 0xc5, 0x9d, 0x7c, 0xb8, 0xdf, 0x47, 0x54, + 0x91, 0x3f, 0x8a, 0xb3, 0x14, 0x5f, 0xbe, 0x73, 0x80, 0xe9, 0xd7, 0xe4, + 0x52, 0x05, 0xa7, 0x5b, 0x34, 0x7a, 0x1e, 0x2a, 0xbf, 0xfe, 0x16, 0xf5, + 0x3a, 0x9c, 0x89, 0x99, 0xce, 0x9d, 0x7f, 0xe5, 0xad, 0xe5, 0xb6, 0x0e, + 0xa7, 0x0e, 0xbf, 0x3e, 0xbd, 0x01, 0x3a, 0xa0, 0xf9, 0xc0, 0x83, 0x50, + 0x8d, 0x7e, 0xc2, 0xda, 0xfa, 0x3e, 0xc7, 0x4e, 0xbe, 0x6b, 0xbb, 0x4d, + 0x16, 0xe5, 0xff, 0xb3, 0x98, 0x3f, 0x3b, 0x9b, 0xb2, 0x75, 0xf8, 0x7f, + 0x7d, 0xf4, 0x75, 0x41, 0xf4, 0x3a, 0x05, 0x6e, 0x8d, 0x7e, 0x11, 0x6a, + 0x12, 0xb7, 0xf9, 0xc7, 0xf9, 0x86, 0x16, 0x75, 0xe5, 0x8a, 0x1d, 0x61, + 0x3a, 0xff, 0xba, 0x07, 0xd6, 0x60, 0xa8, 0x75, 0xfb, 0x4f, 0xbb, 0x84, + 0xeb, 0x20, 0x4f, 0x7b, 0xc6, 0xf5, 0x08, 0xae, 0xc1, 0xae, 0xb6, 0xdf, + 0xf4, 0x38, 0xf7, 0x30, 0x5a, 0x75, 0xfe, 0xf7, 0x92, 0x75, 0xc0, 0x9d, + 0x52, 0x3e, 0x6c, 0x34, 0xbf, 0xe8, 0x10, 0x2e, 0x35, 0xe4, 0x3a, 0xf8, + 0x31, 0x9c, 0x3a, 0xfd, 0xf3, 0x7d, 0x22, 0x87, 0x59, 0xe7, 0x3c, 0xbd, + 0xc8, 0x2f, 0xfe, 0x96, 0x75, 0x38, 0x1e, 0xc0, 0xb4, 0xeb, 0xfd, 0xbc, + 0xa0, 0x7d, 0x9f, 0x9d, 0x7d, 0xaf, 0xd3, 0xc7, 0x53, 0xa3, 0x03, 0x45, + 0x20, 0x42, 0xfa, 0x67, 0x7f, 0xf7, 0x93, 0xf8, 0x90, 0x7b, 0x02, 0xd3, + 0xa8, 0xeb, 0xc0, 0x7f, 0x1d, 0x70, 0x20, 0xea, 0x91, 0xb0, 0xf0, 0xdd, + 0x1d, 0x7d, 0xbb, 0x53, 0x87, 0x5e, 0x85, 0xb1, 0x88, 0x87, 0xdc, 0xe9, + 0x64, 0x3e, 0x0a, 0xa8, 0x4c, 0x65, 0x21, 0x95, 0x78, 0x7d, 0xb6, 0x75, + 0xff, 0x49, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xa1, 0xe9, 0x0f, 0x8d, 0xc7, + 0xaf, 0xdf, 0xc3, 0x71, 0x67, 0x5f, 0x44, 0xd8, 0x13, 0xab, 0x87, 0x91, + 0xa2, 0x7b, 0xfe, 0xc8, 0x0f, 0x63, 0x6a, 0x26, 0x3a, 0xff, 0x7e, 0x9d, + 0xee, 0x7e, 0xe7, 0x52, 0xcf, 0xb7, 0xf3, 0xaa, 0x84, 0x59, 0x3c, 0x23, + 0xef, 0xfc, 0xe1, 0x80, 0xf5, 0x05, 0x16, 0x75, 0xff, 0xda, 0x81, 0x9b, + 0x07, 0xf7, 0xf6, 0x1d, 0x7f, 0xb4, 0x06, 0xe7, 0x86, 0x0e, 0xa5, 0xa2, + 0xbb, 0xa7, 0x7e, 0x42, 0xbf, 0xf8, 0x12, 0xeb, 0xf3, 0x7f, 0x42, 0x4e, + 0x75, 0xff, 0x44, 0xa3, 0x93, 0xc7, 0x27, 0x3a, 0xfc, 0x9e, 0xd3, 0xa1, + 0xd7, 0xfd, 0xcf, 0xf8, 0xe3, 0xec, 0xfc, 0xea, 0xfc, 0xf7, 0x80, 0x4b, + 0x7b, 0xef, 0x24, 0x75, 0xfd, 0xf7, 0xc0, 0x8c, 0x9c, 0xea, 0x91, 0xe6, + 0xcc, 0x3d, 0x7f, 0xf3, 0x46, 0x3c, 0x39, 0xb3, 0x39, 0x23, 0xaf, 0xf8, + 0x02, 0xa7, 0xde, 0xf4, 0x1a, 0x3a, 0xff, 0x08, 0xbf, 0xbe, 0xc3, 0x4e, + 0xbe, 0x1f, 0xe7, 0xfc, 0xea, 0xc3, 0xd6, 0x43, 0x2b, 0xfd, 0xaf, 0x9e, + 0xf8, 0x1c, 0x13, 0xad, 0xf9, 0xd6, 0x4d, 0xcf, 0x1f, 0x86, 0xd7, 0xe7, + 0xdf, 0x5e, 0x43, 0xaa, 0x13, 0xae, 0xc2, 0x34, 0x43, 0xec, 0x24, 0x85, + 0x9f, 0x45, 0x17, 0xe7, 0x02, 0x91, 0xf4, 0xeb, 0xf2, 0xab, 0x39, 0x1a, + 0x3a, 0xa6, 0x3d, 0x31, 0x29, 0xbf, 0xe7, 0xd4, 0x4d, 0xbc, 0xb3, 0x61, + 0xd7, 0xff, 0xe0, 0xf6, 0x3e, 0xb1, 0xe1, 0x7f, 0xf5, 0xa8, 0xfc, 0xab, + 0x83, 0x87, 0x5f, 0xa7, 0x89, 0xdf, 0x47, 0x56, 0x22, 0x59, 0x16, 0x5c, + 0x56, 0xef, 0xc0, 0x75, 0xfc, 0xff, 0xcc, 0x30, 0x13, 0xaa, 0x0f, 0x13, + 0xa2, 0xf6, 0x61, 0x58, 0x6c, 0x1b, 0x15, 0xb4, 0x35, 0x5e, 0x78, 0xab, + 0x39, 0xc4, 0x32, 0x25, 0x08, 0x00, 0xc3, 0xfb, 0x21, 0xfc, 0xa1, 0xb3, + 0x61, 0xc1, 0xbc, 0x25, 0x10, 0x86, 0x68, 0xd0, 0x79, 0x1a, 0xba, 0xe1, + 0x15, 0xd8, 0xc6, 0x9e, 0x1a, 0x9f, 0x98, 0x0a, 0x2e, 0xa1, 0x2f, 0xe9, + 0x43, 0xc0, 0x85, 0x66, 0xc2, 0x2d, 0xb8, 0x68, 0xfd, 0x71, 0xbf, 0x98, + 0x9e, 0x39, 0x25, 0x9d, 0x7f, 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x8b, 0xce, + 0xa1, 0xd2, 0x14, 0x49, 0xbc, 0x31, 0x81, 0x65, 0x2c, 0x37, 0x79, 0x50, + 0x1c, 0x8d, 0x99, 0x6a, 0x7d, 0x85, 0x50, 0xd6, 0x12, 0x9a, 0x8f, 0x17, + 0x61, 0x7d, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x29, 0x6b, 0xf7, 0x1a, + 0xee, 0xd3, 0x45, 0x85, 0x7f, 0xfe, 0x8c, 0x10, 0xc7, 0x63, 0x7f, 0x60, + 0xba, 0xce, 0xbf, 0x81, 0xc4, 0x9d, 0xd6, 0x75, 0x98, 0xc4, 0x58, 0xac, + 0xcf, 0x6d, 0x46, 0xff, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x16, 0x5d, 0xdc, + 0x50, 0xeb, 0xe6, 0x14, 0x55, 0x95, 0x83, 0xaf, 0x31, 0xf5, 0x67, 0x53, + 0x4f, 0x34, 0x05, 0xd4, 0x28, 0x86, 0xd3, 0x25, 0xbf, 0x3a, 0xe5, 0x27, + 0x3a, 0xe7, 0xe4, 0x8d, 0x4e, 0x08, 0xdf, 0xf3, 0xee, 0x39, 0xbf, 0xa1, + 0x43, 0xaf, 0xf4, 0xfb, 0xea, 0x03, 0xe4, 0x3a, 0xfd, 0x19, 0xb2, 0x34, + 0x75, 0xa1, 0xcf, 0x6d, 0x93, 0x4a, 0x74, 0x5d, 0x8c, 0x25, 0x2f, 0x9e, + 0x52, 0x09, 0xd7, 0xf3, 0xf2, 0x3c, 0xfd, 0x3a, 0xf3, 0x2c, 0xb2, 0x55, + 0xff, 0x44, 0xb7, 0xf7, 0x23, 0x37, 0x29, 0x82, 0xfe, 0xff, 0x80, 0xfb, + 0xe7, 0x93, 0x76, 0x4e, 0xba, 0x34, 0x75, 0x05, 0x30, 0x3e, 0x90, 0x8a, + 0x56, 0x92, 0x76, 0x1d, 0x5f, 0xc8, 0xfa, 0xff, 0x40, 0x3a, 0xff, 0xfe, + 0xea, 0x7b, 0xb9, 0xa1, 0xc5, 0x83, 0x5d, 0x79, 0x1d, 0x7f, 0xa2, 0x5e, + 0x7e, 0xb8, 0x4e, 0xac, 0x44, 0x57, 0x16, 0x6d, 0x23, 0xad, 0x23, 0xad, + 0x23, 0xaa, 0x0d, 0x82, 0x82, 0x08, 0x21, 0x7f, 0xfe, 0xf6, 0x91, 0xb8, + 0x3c, 0x81, 0xc0, 0xe2, 0x87, 0x5b, 0x73, 0xae, 0xd0, 0x0e, 0xac, 0x3f, + 0x9d, 0x29, 0x78, 0x46, 0xe4, 0x83, 0xaf, 0xe1, 0x85, 0x8c, 0x61, 0xd7, + 0x4a, 0x0e, 0xa0, 0x9e, 0x94, 0xc2, 0x80, 0x29, 0xbf, 0xff, 0xfe, 0xec, + 0x7b, 0x49, 0xad, 0x47, 0xba, 0x91, 0xcf, 0xd6, 0xf2, 0x97, 0x94, 0x3a, + 0xe4, 0xdc, 0xeb, 0xa1, 0x67, 0x5f, 0xff, 0xd2, 0x81, 0x04, 0xa5, 0x1e, + 0xee, 0x2f, 0xec, 0x7e, 0x75, 0xcd, 0x62, 0x17, 0x82, 0xa7, 0x4b, 0x0c, + 0x39, 0xb2, 0x32, 0x96, 0xa6, 0x72, 0x16, 0xee, 0xa4, 0x30, 0xa6, 0xd4, + 0x20, 0x3c, 0x61, 0xb1, 0xfb, 0x6c, 0x5b, 0xe8, 0xad, 0xff, 0xe6, 0x16, + 0xf2, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x28, 0xcb, 0xf6, 0xc8, 0xe4, 0x7e, + 0x75, 0xf8, 0x5f, 0xf8, 0xfa, 0x75, 0xff, 0xdb, 0xb5, 0x39, 0xdc, 0xc1, + 0x96, 0x8e, 0xb3, 0x10, 0x89, 0x4e, 0x94, 0xf8, 0xa2, 0xa4, 0xc9, 0xf9, + 0xe4, 0x3c, 0x16, 0x72, 0xf3, 0xd9, 0xfa, 0x87, 0x07, 0xa1, 0xd7, 0x7f, + 0xf3, 0x0f, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x39, 0xbf, 0xfc, 0xc2, + 0xde, 0x4c, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0xe5, 0x7f, 0x98, 0xce, 0x35, + 0xdd, 0xa6, 0x8b, 0x32, 0xff, 0xa5, 0xa7, 0x5b, 0x1d, 0xf7, 0xe7, 0x5f, + 0xf2, 0xae, 0x0e, 0x2e, 0x37, 0x85, 0x9d, 0x7f, 0xdf, 0xf2, 0x3d, 0xd7, + 0xde, 0x47, 0x5f, 0xec, 0xd7, 0x39, 0x9b, 0xe8, 0xeb, 0xfb, 0x8d, 0xeb, + 0xa2, 0xa4, 0xeb, 0xb7, 0x59, 0xd6, 0x61, 0x58, 0x47, 0x94, 0x1f, 0x48, + 0xe8, 0x06, 0x7b, 0x66, 0x17, 0xf9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0xb7, + 0x6f, 0xe1, 0x76, 0x39, 0x3f, 0x4e, 0xbc, 0x9b, 0xfe, 0x75, 0xfb, 0x8d, + 0x77, 0x69, 0xa2, 0x90, 0xbf, 0xf6, 0x75, 0x36, 0x77, 0x30, 0x5a, 0x75, + 0xe7, 0x93, 0x18, 0x7e, 0x1a, 0x33, 0xb3, 0x0d, 0x47, 0x77, 0x0b, 0x97, + 0x08, 0xdb, 0xff, 0x98, 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x95, + 0x4e, 0xb8, 0x4d, 0x32, 0x8a, 0xd5, 0xdc, 0xff, 0xf8, 0xcb, 0x45, 0x63, + 0xd1, 0x96, 0xed, 0x1e, 0x5f, 0xe9, 0x20, 0xfb, 0x10, 0x27, 0x5e, 0xd0, + 0x16, 0x75, 0x98, 0xdc, 0xf3, 0x10, 0xc2, 0xf0, 0xbc, 0x8e, 0xbf, 0xf3, + 0xc9, 0x8c, 0xe3, 0x5d, 0xda, 0x68, 0x9d, 0xae, 0x9d, 0x5c, 0xeb, 0xff, + 0xf2, 0x04, 0x0b, 0x8d, 0xa7, 0x08, 0xc0, 0xe3, 0x4e, 0xbf, 0xe8, 0x94, + 0x72, 0x78, 0xe4, 0xe7, 0x59, 0x8c, 0x4c, 0x2d, 0x63, 0x5d, 0x4a, 0x71, + 0xa1, 0x54, 0xbf, 0xfe, 0x63, 0xee, 0xdb, 0x8f, 0xf9, 0xe8, 0x14, 0xfc, + 0xeb, 0xff, 0x9d, 0x7d, 0xc6, 0xbf, 0x63, 0xec, 0x8e, 0xbc, 0x81, 0x73, + 0xaf, 0xfe, 0x1c, 0xeb, 0xcf, 0x9a, 0x17, 0xdc, 0xeb, 0xb6, 0xd8, 0x0a, + 0x28, 0x3a, 0x89, 0xa1, 0xaa, 0x92, 0xab, 0x75, 0xc6, 0x69, 0xa4, 0xfd, + 0xb8, 0x7a, 0x5f, 0xff, 0xc1, 0x7f, 0x31, 0x9a, 0x81, 0xdf, 0xfd, 0x6a, + 0x3f, 0x3a, 0xfd, 0xc6, 0xbb, 0xb4, 0xd1, 0x16, 0x5f, 0xf9, 0xe4, 0xc6, + 0x71, 0xae, 0xed, 0x34, 0x4b, 0xb7, 0xff, 0xf6, 0x07, 0xb1, 0xf5, 0x8f, + 0x0b, 0xff, 0xad, 0x47, 0xe5, 0x59, 0x8c, 0x46, 0xda, 0xcc, 0xf6, 0xd2, + 0xaf, 0xff, 0x30, 0xb7, 0x93, 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x31, 0x5f, + 0xb8, 0xd7, 0x76, 0x9a, 0x2a, 0x9b, 0x61, 0xd5, 0x87, 0x84, 0xa1, 0x9d, + 0xff, 0xff, 0xee, 0x3f, 0x77, 0x96, 0x79, 0x8e, 0xbe, 0xb8, 0x8c, 0xfb, + 0xa9, 0xc9, 0x1d, 0x4c, 0x22, 0x71, 0xc8, 0xaf, 0xff, 0x30, 0xb7, 0x93, + 0x19, 0xc6, 0xbb, 0xb4, 0xd1, 0x3a, 0x5f, 0xe4, 0x7e, 0x44, 0x9f, 0x61, + 0xd7, 0xe9, 0xa2, 0x68, 0xd1, 0xd7, 0xf3, 0x38, 0x9b, 0x30, 0x4e, 0xa4, + 0x3d, 0x5d, 0x14, 0x5e, 0x4e, 0xc1, 0xcc, 0x1a, 0x1b, 0xff, 0x81, 0xaf, + 0x46, 0xec, 0x02, 0x64, 0x59, 0xd4, 0xb3, 0xf2, 0xe9, 0x5d, 0xff, 0x9e, + 0x4c, 0x67, 0x1a, 0xee, 0xd3, 0x44, 0xef, 0x7e, 0xf0, 0x1d, 0x68, 0x55, + 0xff, 0x86, 0x3d, 0x9a, 0xcc, 0xde, 0x47, 0x50, 0x53, 0xe8, 0xc8, 0xc6, + 0x96, 0x44, 0xe9, 0x5e, 0x26, 0xbf, 0xa1, 0x8f, 0xc7, 0x02, 0x75, 0x30, + 0x7f, 0x82, 0x9f, 0x7f, 0xf9, 0x85, 0xbc, 0x98, 0xce, 0x35, 0xdd, 0xa6, + 0x8a, 0x16, 0xff, 0xff, 0xf7, 0x40, 0xb5, 0xbc, 0x98, 0x6f, 0x41, 0xe8, + 0x1c, 0x9d, 0x40, 0x44, 0xc7, 0x5f, 0x81, 0xbf, 0x91, 0xa7, 0x5f, 0xb3, + 0xfc, 0x71, 0x3a, 0xf4, 0x7e, 0xc4, 0xe7, 0x9a, 0x25, 0x14, 0x88, 0xfd, + 0x18, 0x64, 0x5f, 0xfe, 0x61, 0x6f, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, + 0x92, 0xbf, 0xff, 0xd9, 0xa6, 0x3e, 0xe4, 0xdd, 0x75, 0xfb, 0xb1, 0xe0, + 0x2c, 0xea, 0x85, 0xfd, 0xb9, 0xe3, 0x38, 0x91, 0xcb, 0x63, 0x35, 0xe1, + 0x1a, 0xe5, 0x5d, 0xfe, 0x45, 0xe8, 0xd5, 0x00, 0x4d, 0xb6, 0xaf, 0x7f, + 0x98, 0xce, 0x35, 0xdd, 0xa6, 0x88, 0x92, 0xff, 0xf3, 0x0b, 0x79, 0x31, + 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0xf5, 0xf7, 0x01, 0xed, 0x1d, 0x7e, 0xe7, + 0xeb, 0x4d, 0x1d, 0x7a, 0x07, 0x73, 0xaf, 0xde, 0xfa, 0xb1, 0x83, 0xac, + 0x9d, 0x3c, 0x31, 0x1b, 0xbf, 0xfd, 0xdd, 0x90, 0x3f, 0xab, 0xe0, 0x73, + 0x9b, 0x9d, 0x74, 0x78, 0xeb, 0xff, 0xc0, 0x0a, 0x73, 0xec, 0xdb, 0x40, + 0x71, 0x98, 0xea, 0x92, 0x36, 0x90, 0x9b, 0xf4, 0xfd, 0x0a, 0xdf, 0xfc, + 0xf3, 0x6a, 0x36, 0x3f, 0x63, 0x79, 0x8e, 0xbf, 0x64, 0xf9, 0xa5, 0x9d, + 0x7f, 0xf4, 0xdf, 0x3e, 0x8c, 0x6c, 0x7d, 0x91, 0x31, 0xd4, 0x75, 0xfd, + 0x34, 0x9f, 0xcf, 0xb0, 0xea, 0x84, 0x42, 0xe2, 0x63, 0x85, 0x5d, 0xc8, + 0x3a, 0x82, 0xab, 0x65, 0x08, 0xa6, 0x8d, 0x17, 0x87, 0xa2, 0x8f, 0xb2, + 0x15, 0x9b, 0x45, 0xb7, 0x83, 0x82, 0x75, 0xc1, 0xdc, 0xeb, 0xfe, 0x47, + 0x10, 0x7a, 0x68, 0x50, 0xeb, 0xff, 0xe4, 0xe7, 0xce, 0xc2, 0x7b, 0x40, + 0x68, 0x20, 0xeb, 0xe4, 0x9f, 0xf5, 0x73, 0xaf, 0x9a, 0xee, 0xd3, 0x45, + 0x2f, 0x7c, 0x3e, 0x8e, 0x1d, 0x7f, 0xd9, 0xc5, 0x7c, 0x0e, 0x73, 0x73, + 0xa9, 0x0f, 0x6f, 0x61, 0x05, 0x28, 0x99, 0x0c, 0xca, 0x1c, 0x26, 0xec, + 0x22, 0x2f, 0xc3, 0xe9, 0xf1, 0x93, 0xaf, 0xfd, 0x03, 0x1d, 0xf8, 0x01, + 0x03, 0x4e, 0xbc, 0x07, 0xd1, 0xd7, 0xe8, 0xfd, 0xf7, 0xd1, 0xd7, 0x85, + 0x3f, 0x3a, 0xf6, 0x7b, 0x47, 0x54, 0x1b, 0x6d, 0x0d, 0xd0, 0x51, 0xaf, + 0x31, 0xf7, 0xe3, 0x7e, 0x5e, 0xbf, 0x2b, 0xb8, 0x87, 0x68, 0xeb, 0xfe, + 0xff, 0x5c, 0x8d, 0xe4, 0x8b, 0x3a, 0xf7, 0x9f, 0x61, 0xd7, 0xfc, 0xf3, + 0xfc, 0x9c, 0x13, 0x42, 0xb9, 0xd5, 0x08, 0x97, 0x73, 0xa0, 0x0e, 0xdf, + 0xf2, 0x6a, 0x64, 0x1f, 0x47, 0xe7, 0x54, 0x8f, 0x99, 0x65, 0xd7, 0x38, + 0x9d, 0x7f, 0xd1, 0xff, 0xce, 0xc2, 0xdc, 0x4e, 0xb7, 0x37, 0x3c, 0xdd, + 0x82, 0x95, 0x09, 0xe1, 0xe4, 0x65, 0x28, 0xdf, 0x7b, 0x90, 0xb3, 0xaf, + 0xe8, 0x19, 0xbc, 0x8a, 0x1d, 0x7f, 0xd2, 0xce, 0x4d, 0x83, 0x0b, 0x3a, + 0xfd, 0xfc, 0x37, 0x16, 0x75, 0x21, 0xef, 0x70, 0xde, 0xe9, 0x61, 0xd7, + 0xa3, 0xfd, 0x1d, 0x50, 0x7a, 0x41, 0x21, 0x64, 0x56, 0xfd, 0xd0, 0x29, + 0x82, 0x75, 0xff, 0x47, 0x74, 0xfe, 0x8e, 0x6d, 0x1d, 0x7f, 0xe5, 0xb8, + 0x7e, 0xcd, 0x28, 0x1d, 0xce, 0xa0, 0x9f, 0xda, 0x1d, 0x5f, 0x73, 0xff, + 0xbb, 0x0e, 0xbc, 0x8c, 0xf8, 0xea, 0xe9, 0xe1, 0xe8, 0x9e, 0x82, 0x99, + 0x47, 0x61, 0x45, 0xe6, 0x4b, 0xfe, 0xfd, 0x3b, 0x9c, 0x79, 0xb4, 0x75, + 0xff, 0xfa, 0x24, 0x31, 0x3f, 0xd9, 0xb5, 0xdc, 0xda, 0xe7, 0xe7, 0x5f, + 0xdf, 0x17, 0x9e, 0x7f, 0x1d, 0x66, 0x9d, 0x76, 0xfa, 0xc3, 0x7c, 0xe5, + 0xd5, 0xba, 0x3f, 0xd6, 0x72, 0xf0, 0x9a, 0xbf, 0xd8, 0xcc, 0x93, 0x40, + 0x59, 0xd7, 0x6c, 0xd1, 0xd7, 0xec, 0x9f, 0x3b, 0xa3, 0xaa, 0x0d, 0xf8, + 0x8c, 0x5e, 0xce, 0x68, 0xea, 0x69, 0xba, 0xd8, 0x3f, 0x7f, 0xdf, 0xc7, + 0xff, 0x76, 0x40, 0xed, 0x1d, 0x50, 0x98, 0x7e, 0x42, 0xb1, 0x08, 0xef, + 0xff, 0xfe, 0xec, 0x73, 0x76, 0xa6, 0xff, 0x14, 0x7f, 0x9a, 0xeb, 0xb6, + 0x04, 0x27, 0x5f, 0x78, 0x51, 0x67, 0x5f, 0xe1, 0x87, 0x1f, 0x60, 0x9d, + 0x7f, 0xba, 0xf3, 0x27, 0x22, 0x73, 0xae, 0xc5, 0x9d, 0x41, 0x4c, 0x37, + 0x1d, 0xd6, 0x40, 0xe5, 0xdb, 0x0c, 0xef, 0xdb, 0x48, 0xb8, 0xd1, 0xd7, + 0xe7, 0xd9, 0x9c, 0xd1, 0xd4, 0x13, 0xd1, 0x59, 0x4d, 0xfb, 0xae, 0x28, + 0xb3, 0xaf, 0x94, 0x9b, 0x50, 0x75, 0xfe, 0x7f, 0xf5, 0x1d, 0x8d, 0x1d, + 0x50, 0x89, 0xcc, 0x22, 0x42, 0x51, 0x23, 0xbb, 0xf6, 0x9d, 0x6d, 0x1d, + 0x72, 0x29, 0xa3, 0x4e, 0x01, 0x7b, 0xdf, 0xbb, 0x4e, 0xbf, 0xff, 0x20, + 0x73, 0x63, 0xf2, 0x6f, 0xb2, 0x7f, 0x3a, 0xce, 0xa8, 0x3f, 0x4e, 0x0e, + 0x59, 0x88, 0x66, 0xed, 0xce, 0xeb, 0x21, 0xa0, 0x8b, 0xe4, 0x6b, 0x3b, + 0xa2, 0xa4, 0x3f, 0xe6, 0x94, 0x05, 0xc3, 0x45, 0x8d, 0xf6, 0x1b, 0xaf, + 0x1a, 0xbf, 0xf1, 0x9a, 0x8c, 0x68, 0x9a, 0x8d, 0x03, 0xd1, 0x9c, 0x6d, + 0xb0, 0x7d, 0x85, 0x0d, 0xfe, 0x63, 0x38, 0xd7, 0x76, 0x9a, 0x29, 0xcb, + 0xff, 0x27, 0x1f, 0x5d, 0xcc, 0x16, 0x9d, 0x7e, 0x5f, 0x39, 0x9a, 0x3a, + 0xff, 0xfd, 0xd0, 0x7b, 0x91, 0xed, 0x63, 0x75, 0x1c, 0x69, 0xd7, 0xf9, + 0x16, 0x18, 0xd0, 0x04, 0xeb, 0xfb, 0x3d, 0xbc, 0xa1, 0x93, 0xaf, 0xfe, + 0x51, 0x37, 0xd0, 0xe0, 0x7a, 0xec, 0x9d, 0x7f, 0xec, 0xec, 0x73, 0x18, + 0x65, 0x96, 0x4a, 0xb9, 0x19, 0x3a, 0xe9, 0xd8, 0x0a, 0x76, 0x58, 0x76, + 0xd2, 0x7e, 0xaa, 0x89, 0x8f, 0x8b, 0xb6, 0xd1, 0x76, 0x90, 0x6f, 0xdc, + 0x6b, 0xbb, 0x4d, 0x15, 0xe5, 0xff, 0xfd, 0x81, 0xec, 0x7d, 0x63, 0xc2, + 0xff, 0xeb, 0x51, 0xf9, 0x56, 0x63, 0x11, 0x23, 0xb6, 0x67, 0x7f, 0xf3, + 0x0f, 0x26, 0x33, 0x8d, 0x77, 0x69, 0xa2, 0x47, 0xbc, 0xdc, 0x59, 0xd7, + 0x93, 0xf8, 0x3a, 0xf3, 0x71, 0x65, 0x30, 0x5d, 0xdf, 0xb8, 0xd7, 0x76, + 0x9a, 0x24, 0x8b, 0xff, 0xfa, 0x13, 0x89, 0xb5, 0x03, 0x3c, 0x79, 0x3a, + 0xf3, 0x9d, 0x74, 0x98, 0x84, 0x5c, 0xe1, 0x5f, 0x4c, 0xef, 0xd9, 0xd6, + 0x31, 0x67, 0x59, 0x88, 0x4d, 0x45, 0xe1, 0xdf, 0xe3, 0xbb, 0xff, 0x98, + 0x79, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x55, 0xfb, 0x8d, 0x77, 0x69, + 0xa2, 0xf1, 0xbf, 0xe9, 0x31, 0x9c, 0x6b, 0xbb, 0x4d, 0x12, 0x6d, 0x98, + 0xc3, 0xf8, 0x73, 0x3b, 0x99, 0xe9, 0xd7, 0xe4, 0xff, 0x58, 0x27, 0x5f, + 0xff, 0x01, 0xf7, 0xcc, 0x51, 0x47, 0x96, 0x6f, 0xe3, 0xaa, 0x47, 0xef, + 0xa2, 0x6b, 0xdf, 0x46, 0x73, 0xae, 0xe7, 0x8e, 0xbd, 0x30, 0xce, 0x75, + 0x84, 0xeb, 0xbe, 0xfd, 0x3a, 0xbf, 0x35, 0x3f, 0x43, 0xee, 0xdb, 0x62, + 0x13, 0x4e, 0xc8, 0x47, 0x74, 0x89, 0xc7, 0xb4, 0x2d, 0xf5, 0x1a, 0xa1, + 0xba, 0x3f, 0x9c, 0xfe, 0x55, 0x88, 0x58, 0x63, 0x3c, 0x48, 0xfc, 0x66, + 0x8c, 0x55, 0x65, 0x9d, 0x8e, 0x8b, 0xc7, 0x60, 0x86, 0x4f, 0xd8, 0xdd, + 0x6a, 0x25, 0xfe, 0x10, 0x4f, 0x29, 0x1a, 0x53, 0xae, 0xe1, 0x9d, 0x4a, + 0xcc, 0x46, 0xc3, 0x29, 0x38, 0xdc, 0xdb, 0xd4, 0xdd, 0xde, 0xb2, 0xe3, + 0x4a, 0x4b, 0xea, 0xbc, 0xa2, 0x39, 0xad, 0x86, 0x3f, 0x2d, 0x09, 0x92, + 0xf3, 0x6c, 0x87, 0xed, 0x2a, 0x31, 0xed, 0x94, 0x17, 0xf3, 0xe6, 0xaa, + 0x98, 0xf8, 0xc6, 0xb2, 0xb6, 0xd5, 0x6e, 0x23, 0xeb, 0xd4, 0xa9, 0x05, + 0xaf, 0xeb, 0xd9, 0x4a, 0xc8, 0x66, 0x72, 0x5f, 0x6e, 0x5c, 0x3f, 0xda, + 0x41, 0x46, 0xd5, 0x75, 0xd5, 0x40, }; -static const unsigned kPreloadedHSTSBits = 213993; +static const unsigned kPreloadedHSTSBits = 265770; -static const unsigned kHSTSRootPosition = 213387; +static const unsigned kHSTSRootPosition = 265157; #endif // NET_HTTP_TRANSPORT_SECURITY_STATE_STATIC_H_ diff --git a/chromium/net/http/transport_security_state_static.json b/chromium/net/http/transport_security_state_static.json index 841a9ff148c..4bff1eab791 100644 --- a/chromium/net/http/transport_security_state_static.json +++ b/chromium/net/http/transport_security_state_static.json @@ -13,6 +13,8 @@ // static_spki_hashes: (list of strings) the set of allowed SPKIs hashes // bad_static_spki_hashes: (optional list of strings) the set of forbidden // SPKIs hashes +// report_uri: (optional string) the URI to send violation reports to; +// reports will be in the format defined in RFC 7469 // // For a given pinset, a certificate is accepted if at least one of the // "static_spki_hashes" SPKIs is found in the chain and none of the @@ -23,6 +25,9 @@ // name: (string) the DNS name of the host in question // include_subdomains: (optional bool) whether subdomains of |name| are also // covered +// include_subdomains_for_pinning: (optional bool) whether subdomains +// of |name| are also covered for pinning. |include_subdomains| +// implies this. // mode: (optional string) "force-https" iff covered names should require // HTTPS // pins: (optional string) the |name| member of an object in |pinsets| @@ -41,7 +46,8 @@ "GoogleBackup2048", "GoogleG2", "GeoTrustGlobal" - ] + ], + "report_uri": "http://clients3.google.com/cert_upload_json" }, { "name": "tor", @@ -150,7 +156,8 @@ "ThawtePrimaryRootCA_G2", "ThawtePrimaryRootCA_G3", "ThawtePrimaryRootCA" - ] + ], + "report_uri": "https://log.getdropbox.com/hpkp" }, { "name": "facebook", @@ -212,6 +219,9 @@ { "name": "passwords.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, { "name": "myaccount.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, { "name": "contributor.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, + { "name": "fi.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, + { "name": "xn--7xa.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, + { "name": "pixel.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, // Other Google-related domains that must use HTTPS. { "name": "google", "include_subdomains": true, "mode": "force-https", "pins": "google" }, @@ -236,6 +246,8 @@ { "name": "translate.googleapis.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, { "name": "gvt2.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, { "name": "gvt3.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, + { "name": "withyoutube.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, + { "name": "withgoogle.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, { "name": "webfilings.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, { "name": "webfilings-mirror-hrd.appspot.com", "include_subdomains": true, "mode": "force-https", "pins": "google" }, @@ -282,6 +294,8 @@ { "name": "g.co", "include_subdomains": true, "pins": "google" }, { "name": "googletagmanager.com", "include_subdomains": true, "pins": "google" }, { "name": "googletagservices.com", "include_subdomains": true, "pins": "google" }, + { "name": "ggpht.com", "include_subdomains": true, "pins": "google" }, + { "name": "blogspot.com", "include_subdomains": true, "pins": "google" }, { "name": "google.ac", "include_subdomains": true, "pins": "google" }, { "name": "google.ad", "include_subdomains": true, "pins": "google" }, { "name": "google.ae", "include_subdomains": true, "pins": "google" }, @@ -825,8 +839,10 @@ { "name": "z.ai", "include_subdomains": true, "mode": "force-https" }, { "name": "wildbee.org", "include_subdomains": true, "mode": "force-https" }, { "name": "portal.tirol.gv.at", "include_subdomains": true, "mode": "force-https" }, - { "name": "dropbox.com", "mode": "force-https", "pins": "dropbox" }, + { "name": "dropbox.com", "mode": "force-https", "include_subdomains_for_pinning": true, "pins": "dropbox" }, { "name": "www.dropbox.com", "include_subdomains": true, "mode": "force-https", "pins": "dropbox" }, + { "name": "dropboxstatic.com", "include_subdomains_for_pinning": true, "pins": "dropbox" }, + { "name": "dropboxusercontent.com", "include_subdomains_for_pinning": true, "pins": "dropbox" }, { "name": "code-poets.co.uk", "include_subdomains": true, "mode": "force-https" }, { "name": "jackyyf.com", "mode": "force-https" }, { "name": "flynn.io", "include_subdomains": true, "mode": "force-https" }, @@ -1198,7 +1214,6 @@ { "name": "digitaldaddy.net", "include_subdomains": true, "mode": "force-https" }, { "name": "elnutricionista.es", "include_subdomains": true, "mode": "force-https" }, { "name": "fronteers.nl", "include_subdomains": true, "mode": "force-https" }, - { "name": "getssl.uz", "include_subdomains": true, "mode": "force-https" }, { "name": "gunnarhafdal.com", "include_subdomains": true, "mode": "force-https" }, { "name": "heijblok.com", "include_subdomains": true, "mode": "force-https" }, { "name": "kdex.de", "include_subdomains": true, "mode": "force-https" }, @@ -1257,6 +1272,7 @@ { "name": "wepay.in.th", "include_subdomains": true, "mode": "force-https" }, { "name": "zixiao.wang", "include_subdomains": true, "mode": "force-https" }, + { "name": "at.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, { "name": "au.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, { "name": "az.search.yahoo.com", "include_subdomains": false, "mode": "force-https" }, @@ -1621,6 +1637,7 @@ { "name": "webtrh.cz", "include_subdomains": true, "mode": "force-https" }, { "name": "yetii.net", "include_subdomains": true, "mode": "force-https" }, { "name": "login.ubuntu.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "pay.ubuntu.com", "include_subdomains": true, "mode": "force-https" }, { "name": "login.launchpad.net", "include_subdomains": true, "mode": "force-https" }, { "name": "302.nyc", "include_subdomains": true, "mode": "force-https" }, { "name": "biathloncup.ru", "include_subdomains": true, "mode": "force-https" }, @@ -1798,7 +1815,7 @@ { "name": "gaytorrent.ru", "include_subdomains": true, "mode": "force-https" }, { "name": "getable.com", "include_subdomains": true, "mode": "force-https" }, { "name": "gpsfix.cz", "include_subdomains": true, "mode": "force-https" }, - { "name": "guidetoiceland.is", "include_subdomains": true, "mode": "force-https" }, + { "name": "guidetoiceland.is", "include_subdomains": false, "mode": "force-https" }, { "name": "happylifestyle.com", "include_subdomains": true, "mode": "force-https" }, { "name": "heppler.net", "include_subdomains": true, "mode": "force-https" }, { "name": "httpswatch.com", "include_subdomains": true, "mode": "force-https" }, @@ -1819,7 +1836,6 @@ { "name": "narodniki.com", "include_subdomains": true, "mode": "force-https" }, { "name": "netrider.net.au", "include_subdomains": true, "mode": "force-https" }, { "name": "niloxy.com", "include_subdomains": true, "mode": "force-https" }, - { "name": "noobs-r-us.co.uk", "include_subdomains": true, "mode": "force-https" }, { "name": "nowhere.dk", "include_subdomains": true, "mode": "force-https" }, { "name": "perfectionis.me", "include_subdomains": true, "mode": "force-https" }, { "name": "phryanjr.com", "include_subdomains": true, "mode": "force-https" }, @@ -2190,7 +2206,6 @@ { "name": "301.website", "include_subdomains": true, "mode": "force-https" }, { "name": "alza.cz", "include_subdomains": true, "mode": "force-https" }, { "name": "armytricka.cz", "include_subdomains": true, "mode": "force-https" }, - { "name": "astaxi.net", "include_subdomains": true, "mode": "force-https" }, { "name": "bradkovach.com", "include_subdomains": true, "mode": "force-https" }, { "name": "crypto.graphics", "include_subdomains": true, "mode": "force-https" }, { "name": "cryptography.io", "include_subdomains": true, "mode": "force-https" }, @@ -2222,7 +2237,6 @@ { "name": "lapetition.be", "include_subdomains": true, "mode": "force-https" }, { "name": "maartenvandekamp.nl", "include_subdomains": true, "mode": "force-https" }, { "name": "mcard.vn", "include_subdomains": true, "mode": "force-https" }, - { "name": "mccrypto.de", "include_subdomains": true, "mode": "force-https" }, { "name": "mcnext.net", "include_subdomains": true, "mode": "force-https" }, { "name": "micropple.net", "include_subdomains": true, "mode": "force-https" }, { "name": "munki.org", "include_subdomains": true, "mode": "force-https" }, @@ -2363,7 +2377,6 @@ { "name": "keeley.gq", "include_subdomains": true, "mode": "force-https" }, { "name": "keeley.ml", "include_subdomains": true, "mode": "force-https" }, { "name": "keybase.io", "include_subdomains": true, "mode": "force-https" }, - { "name": "keycom.co.uk", "include_subdomains": true, "mode": "force-https" }, { "name": "kinganywhere.eu", "include_subdomains": true, "mode": "force-https" }, { "name": "ks-watch.de", "include_subdomains": true, "mode": "force-https" }, { "name": "leakedminecraft.net", "include_subdomains": true, "mode": "force-https" }, @@ -2433,7 +2446,7 @@ { "name": "blablacar.rs", "include_subdomains": true, "mode": "force-https" }, { "name": "blablacar.ru", "include_subdomains": true, "mode": "force-https" }, { "name": "canhazip.com", "include_subdomains": true, "mode": "force-https" }, - { "name": "carbonmade.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "carbonmade.com", "include_subdomains": false, "mode": "force-https" }, { "name": "collinmbarrett.com", "include_subdomains": true, "mode": "force-https" }, { "name": "coloradocomputernetworking.net", "include_subdomains": true, "mode": "force-https" }, { "name": "copperhead.co", "include_subdomains": true, "mode": "force-https" }, @@ -2447,7 +2460,6 @@ { "name": "ethercalc.com", "include_subdomains": true, "mode": "force-https" }, { "name": "ethercalc.org", "include_subdomains": true, "mode": "force-https" }, { "name": "fluxfingers.net", "include_subdomains": true, "mode": "force-https" }, - { "name": "getbambu.com", "include_subdomains": true, "mode": "force-https" }, { "name": "haber1903.com", "include_subdomains": true, "mode": "force-https" }, { "name": "initrd.net", "include_subdomains": true, "mode": "force-https" }, { "name": "integromat.com", "include_subdomains": true, "mode": "force-https" }, @@ -2520,7 +2532,6 @@ { "name": "fidelapp.com", "include_subdomains": true, "mode": "force-https" }, { "name": "floweslawncare.com", "include_subdomains": true, "mode": "force-https" }, { "name": "foxelbox.com", "include_subdomains": true, "mode": "force-https" }, - { "name": "fsma.pl", "include_subdomains": true, "mode": "force-https" }, { "name": "getcolor.com", "include_subdomains": true, "mode": "force-https" }, { "name": "getsello.com", "include_subdomains": true, "mode": "force-https" }, { "name": "gheorghesarcov.ga", "include_subdomains": true, "mode": "force-https" }, @@ -2770,7 +2781,6 @@ { "name": "patechmasters.com", "include_subdomains": true, "mode": "force-https" }, { "name": "payments-reference.org", "include_subdomains": true, "mode": "force-https" }, { "name": "pbprint.ru", "include_subdomains": true, "mode": "force-https" }, - { "name": "phcorner.net", "include_subdomains": true, "mode": "force-https" }, { "name": "pieterhordijk.com", "include_subdomains": true, "mode": "force-https" }, { "name": "poedgirl.com", "include_subdomains": true, "mode": "force-https" }, { "name": "poiema.com.sg", "include_subdomains": true, "mode": "force-https" }, @@ -2913,7 +2923,6 @@ { "name": "cobalt.io", "include_subdomains": true, "mode": "force-https" }, { "name": "dealbanana.it", "include_subdomains": true, "mode": "force-https" }, { "name": "cydia-search.io", "include_subdomains": true, "mode": "force-https" }, - { "name": "delbart.se", "include_subdomains": true, "mode": "force-https" }, { "name": "dotsiam.com", "include_subdomains": true, "mode": "force-https" }, { "name": "clevertarget.ru", "include_subdomains": true, "mode": "force-https" }, { "name": "connext.de", "include_subdomains": true, "mode": "force-https" }, @@ -3122,7 +3131,728 @@ { "name": "ccblog.de", "include_subdomains": true, "mode": "force-https" }, { "name": "smiatek.name", "include_subdomains": true, "mode": "force-https" }, { "name": "korni22.org", "include_subdomains": true, "mode": "force-https" }, - { "name": "student.andover.edu", "include_subdomains": true, "mode": "force-https" } + { "name": "student.andover.edu", "include_subdomains": true, "mode": "force-https" }, + { "name": "0.me.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "agilebits.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "alenan.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "amisharingstuff.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "amunoz.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "appuro.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "askfit.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "axado.com.br", "include_subdomains": true, "mode": "force-https" }, + { "name": "bebesurdoue.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "burnworks.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "canadalife.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "chaosdorf.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "cheerflow.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "chrisbrown.id.au", "include_subdomains": true, "mode": "force-https" }, + { "name": "chromebooksforwork.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "cloudmigrator365.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "cloudpagesforwork.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "clu-in.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "cmc-versand.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "cnlic.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "cocoaheads.at", "include_subdomains": true, "mode": "force-https" }, + { "name": "colorlib.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "corruption-mc.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "corruption-rsps.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "corruption-server.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "cthulhuden.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "dateno1.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "democracy.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "democracychronicles.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "demuzere.be", "include_subdomains": true, "mode": "force-https" }, + { "name": "deviltracks.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "dietrich.cx", "include_subdomains": true, "mode": "force-https" }, + { "name": "dissimulo.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "dlscomputers.com.au", "include_subdomains": true, "mode": "force-https" }, + { "name": "dogoodbehappyllc.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "dreid.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "e-deca2.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "elitehosting.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "empowerdb.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "endlesshorizon.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "entrepreneur.or.id", "include_subdomains": true, "mode": "force-https" }, + { "name": "eol34.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "eroticen.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "eucl3d.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "firmapi.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "formationsfactory.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "freeweibo.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "funchestra.at", "include_subdomains": true, "mode": "force-https" }, + { "name": "gamenected.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "gamenected.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "getsport.mobi", "include_subdomains": true, "mode": "force-https" }, + { "name": "ghostblog.info", "include_subdomains": true, "mode": "force-https" }, + { "name": "gmdu.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "grafitec.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "greatfire.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "greenroach.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "hablemosdetecnologia.com.ve", "include_subdomains": true, "mode": "force-https" }, + { "name": "hardh.at", "include_subdomains": true, "mode": "force-https" }, + { "name": "haveeruexaminer.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "helloacm.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "hurricanelabs.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "hyper-text.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "idndx.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "im-c-shop.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "inbitcoin.it", "include_subdomains": true, "mode": "force-https" }, + { "name": "inspiroinc.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "instant-hack.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "iraqidinar.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "itsagadget.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ivancacic.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "j0s.eu", "include_subdomains": true, "mode": "force-https" }, + { "name": "jamesmaurer.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "jinbo123.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "joshstroup.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "justyy.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "kasko.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "kawaii.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "kazandaemon.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "kbcequitas.hu", "include_subdomains": true, "mode": "force-https" }, + { "name": "keskeces.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "lehighmathcircle.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "lenzw.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "leon-jaekel.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "linuxcommand.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "lognot.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "maclemon.at", "include_subdomains": true, "mode": "force-https" }, + { "name": "maternalsafety.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "max-moeglich.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "mclab.su", "include_subdomains": true, "mode": "force-https" }, + { "name": "mdek.at", "include_subdomains": true, "mode": "force-https" }, + { "name": "meddelare.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "medexpress.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "mediawiki.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "mikaela.info", "include_subdomains": true, "mode": "force-https" }, + { "name": "milahendri.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "moniquedekermadec.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "msebera.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "mypagella.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "necesitodinero.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "obermeiers.eu", "include_subdomains": true, "mode": "force-https" }, + { "name": "ollning.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "omacostudio.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ourbank.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "paysera.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "petersmark.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "phryneas.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "pinesandneedles.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "pmnts.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "qingxuan.info", "include_subdomains": true, "mode": "force-https" }, + { "name": "raah.co", "include_subdomains": true, "mode": "force-https" }, + { "name": "recon-networks.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "renlong.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "reucon.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ristioja.ee", "include_subdomains": true, "mode": "force-https" }, + { "name": "roberthurlbut.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "rugstorene.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "shadowkitsune.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "shaundanielz.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "shellvatore.us", "include_subdomains": true, "mode": "force-https" }, + { "name": "shipcloud.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "simplexsupport.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "slainvet.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "smartlocksmith.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "social-media-strategies.it", "include_subdomains": true, "mode": "force-https" }, + { "name": "sparklingsparklers.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "sportifik.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "tanzhijun.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "tcao.info", "include_subdomains": true, "mode": "force-https" }, + { "name": "teamblueridge.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "tecart-cloud.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "tecart-system.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "tecartcrm.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "techandtux.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "tehrabbitt.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "thehiddenbay.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "ticketmates.com.au", "include_subdomains": true, "mode": "force-https" }, + { "name": "tinyvpn.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "tinyvpn.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "tls1914.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "topnewstoday.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "totalcarcheck.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "toxme.se", "include_subdomains": true, "mode": "force-https" }, + { "name": "trueblueessentials.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "tumutanzi.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "tuzaijidi.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ubicv.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "un-zero-un.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "unionstationapp.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "utonia.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "victorcanera.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "vokeapp.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "waze.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "whitehouse.gov", "include_subdomains": true, "mode": "force-https" }, + { "name": "wikibooks.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "wikimediafoundation.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "wikinews.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "wikiquote.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "wikisource.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "wikiversity.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "wikivoyage.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "wiktionary.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "worcesterfestival.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "x.st", "include_subdomains": true, "mode": "force-https" }, + { "name": "x64architecture.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--datenrettung-mnchen-jbc.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--hfk-allgu-schwaben-stb.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--mgbbh2a9fub.xn--ngbc5azd", "include_subdomains": true, "mode": "force-https" }, + { "name": "yippie.nl", "include_subdomains": true, "mode": "force-https" }, + { "name": "yu.gg", "include_subdomains": true, "mode": "force-https" }, + { "name": "zeno-system.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "track.plus", "include_subdomains": true, "mode": "force-https" }, + { "name": "blog.gov.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "clubmini.jp", "include_subdomains": true, "mode": "force-https" }, + { "name": "codingforspeed.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "cradlepointecm.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "dobet.in", "include_subdomains": true, "mode": "force-https" }, + { "name": "domainexpress.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "ediscomp.sk", "include_subdomains": true, "mode": "force-https" }, + { "name": "edissecurity.sk", "include_subdomains": true, "mode": "force-https" }, + { "name": "ewe2.ninja", "include_subdomains": true, "mode": "force-https" }, + { "name": "fluxent.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "fruitusers.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "gpsvideocanada.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "gracedays.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "inksupply.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "jhburton.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "odin.xxx", "include_subdomains": true, "mode": "force-https" }, + { "name": "pagure.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "pagure.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "silvergoldbull.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "silvergoldbull.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "sunnyfruit.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "szaydon.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "tosecure.link", "include_subdomains": true, "mode": "force-https" }, + { "name": "uploadbeta.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "wholebites.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "wikipedia.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "woresite.jp", "include_subdomains": true, "mode": "force-https" }, + { "name": "agonswim.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "appharbor.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "armory.consulting", "include_subdomains": true, "mode": "force-https" }, + { "name": "armory.supplies", "include_subdomains": true, "mode": "force-https" }, + { "name": "b2and.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "bowlroll.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "bryanquigley.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "cfcnexus.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "clipped4u.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "coffeestrategies.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "cvsoftub.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "dailyenglishchallenge.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "derreichesack.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "devnsec.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "donateaday.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "dragon-chem.eu", "include_subdomains": true, "mode": "force-https" }, + { "name": "eelsden.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "elenag.ga", "include_subdomains": true, "mode": "force-https" }, + { "name": "emailhunter.co", "include_subdomains": true, "mode": "force-https" }, + { "name": "expressvpn.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "factorygw.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "flamingkeys.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "giveattheoffice.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "givingnexus.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "granth.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "happyfabric.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "happygadget.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "illorenese.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "imirhil.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "ipledgeonline.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "junethack.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "mamaison.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "mca2017.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "mnd.sc", "include_subdomains": true, "mode": "force-https" }, + { "name": "modemagazines.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "n-pix.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "open-to-repair.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "panoti.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "philosophyguides.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "pmctire.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "polis.or.at", "include_subdomains": true, "mode": "force-https" }, + { "name": "quppa.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "rc4.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "rot47.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "rusl.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "satmep.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "secctexasgiving.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "secureideas.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "simod.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "simplycharlottemason.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "skoda-clever-lead.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "skoda-im-dialog.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "skoda-nurdiebesten.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "slix.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "speed-mailer.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "steelephys.com.au", "include_subdomains": true, "mode": "force-https" }, + { "name": "stick2bike.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "swift-devedge.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "syntaxnightmare.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "tbrss.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "tokke.dk", "include_subdomains": true, "mode": "force-https" }, + { "name": "unapp.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "valopv.be", "include_subdomains": true, "mode": "force-https" }, + { "name": "varvy.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "videomail.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "welovemail.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "whispeer.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "wm-talk.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "xd.cm", "include_subdomains": true, "mode": "force-https" }, + { "name": "zaufanatrzeciastrona.pl", "include_subdomains": true, "mode": "force-https" }, + { "name": "zx6rninja.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "zachborboa.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "alt.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "badcronjob.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "bankin.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "boris.one", "include_subdomains": true, "mode": "force-https" }, + { "name": "brakstad.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "bulldog-hosting.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "campus-finance.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "cao.la", "include_subdomains": true, "mode": "force-https" }, + { "name": "cashlink.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "ckleemann.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "cloud-project.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "cloudwalk.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "coore.jp", "include_subdomains": true, "mode": "force-https" }, + { "name": "crackingking.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "davidgrudl.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "davisroi.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "didacte.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "dirkwolf.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "dotadata.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "dronepit.dk", "include_subdomains": true, "mode": "force-https" }, + { "name": "duckduckstart.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "e-typ.eu", "include_subdomains": true, "mode": "force-https" }, + { "name": "eleicoes2016.com.br", "include_subdomains": true, "mode": "force-https" }, + { "name": "engelundlicht.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "etaes.eu", "include_subdomains": true, "mode": "force-https" }, + { "name": "ethicaldata.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "floskelwolke.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "geekcast.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "gmta.nl", "include_subdomains": true, "mode": "force-https" }, + { "name": "govtrack.us", "include_subdomains": true, "mode": "force-https" }, + { "name": "guilde-vindicta.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "hisbrucker.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "hledejlevne.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "hookandloom.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "hranicka.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "hsts.date", "include_subdomains": true, "mode": "force-https" }, + { "name": "ipv6-adresse.dk", "include_subdomains": true, "mode": "force-https" }, + { "name": "iqboxy.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ivk.website", "include_subdomains": true, "mode": "force-https" }, + { "name": "jacekowski.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "kermadec.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "latrine.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "ldc.com.br", "include_subdomains": true, "mode": "force-https" }, + { "name": "leominstercu.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "lmddgtfy.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "lmsptfy.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "madrants.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "marktboten.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "melf.nl", "include_subdomains": true, "mode": "force-https" }, + { "name": "meteosky.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "mirtes.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "mitchellrenouf.ca", "include_subdomains": true, "mode": "force-https" }, + { "name": "munzee.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "musikkfondene.no", "include_subdomains": true, "mode": "force-https" }, + { "name": "mydeos.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "myraytech.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "nethackwiki.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "nette.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "only-roses.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "openkvk.nl", "include_subdomains": true, "mode": "force-https" }, + { "name": "phpfashion.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "pleier-it.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "pleier.it", "include_subdomains": true, "mode": "force-https" }, + { "name": "recommended.reviews", "include_subdomains": true, "mode": "force-https" }, + { "name": "reddit.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "remoteutilities.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "rj.gg", "include_subdomains": true, "mode": "force-https" }, + { "name": "rtcx.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "runementors.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "rusl.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "sellme.biz", "include_subdomains": true, "mode": "force-https" }, + { "name": "shopapi.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "silentkernel.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "skimming.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "skoleniphp.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "smb445.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "sobabox.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "soply.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "sweetll.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "taskstream.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "thedreamtravelgroup.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "thehotfix.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "tiffnix.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "tomli.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "vivendi.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "vsean.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "wesleycabus.be", "include_subdomains": true, "mode": "force-https" }, + { "name": "wover.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "wpserp.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "z0rro.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "zhihua-lai.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "1017scribes.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "anfsanchezo.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "bcvps.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "beautykat.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "bevapehappy.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "bouncyballs.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "bvalle.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "cafe-scientifique.org.ec", "include_subdomains": true, "mode": "force-https" }, + { "name": "caveclan.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "chaletmanager.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "changetip.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ciscodude.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "crysadm.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "cuvva.co", "include_subdomains": true, "mode": "force-https" }, + { "name": "de-spil.be", "include_subdomains": true, "mode": "force-https" }, + { "name": "dolphin-cloud.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "dolphin-hosting.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "dolphin-it.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "enquos.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "flipagram.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "gravity-net.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "gtanda.tk", "include_subdomains": true, "mode": "force-https" }, + { "name": "hannover-banditen.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "hdc.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "instacart.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "intarweb.ca", "include_subdomains": true, "mode": "force-https" }, + { "name": "kirkpatrickdavis.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "maarten.nyc", "include_subdomains": true, "mode": "force-https" }, + { "name": "mantor.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "motionpicturesolutions.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "motocyklovedily.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "parasitologyclub.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "phongmay24h.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "pilgermaske.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "pol.in.th", "include_subdomains": true, "mode": "force-https" }, + { "name": "puyblanc.info", "include_subdomains": true, "mode": "force-https" }, + { "name": "rantanda.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "redd.it", "include_subdomains": true, "mode": "force-https" }, + { "name": "respice.xyz", "include_subdomains": true, "mode": "force-https" }, + { "name": "rewardstock.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "rr.in.th", "include_subdomains": true, "mode": "force-https" }, + { "name": "salserototal.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "schallert.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "section.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "secureradio.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "simplelearner.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "tlo.link", "include_subdomains": true, "mode": "force-https" }, + { "name": "tlo.xyz", "include_subdomains": true, "mode": "force-https" }, + { "name": "typewolf.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "vorlif.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "xellos.ml", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--4dbjwf8c.cf", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--4dbjwf8c.ga", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--4dbjwf8c.ml", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--4dbjwf8c.tk", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--lgb3a8bcpn.cf", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--lgb3a8bcpn.ga", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--lgb3a8bcpn.gq", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--lgb3a8bcpn.ml", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--ls8hi7a.tk", "include_subdomains": true, "mode": "force-https" }, + { "name": "yyyy.xyz", "include_subdomains": true, "mode": "force-https" }, + { "name": "zhaojin97.cn", "include_subdomains": true, "mode": "force-https" }, + { "name": "www.icann.org", "mode": "force-https" }, + { "name": "368mibn.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "888sport.dk", "include_subdomains": true, "mode": "force-https" }, + { "name": "aevpn.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "andreigec.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "arnaudfeld.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "beneffy.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "brrr.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "charge.co", "include_subdomains": true, "mode": "force-https" }, + { "name": "cloudspace-analytics.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "comiteshopping.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "coreless-stretchfilm.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "crudysql.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "csgokings.eu", "include_subdomains": true, "mode": "force-https" }, + { "name": "dank.ninja", "include_subdomains": true, "mode": "force-https" }, + { "name": "demuzere.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "demuzere.eu", "include_subdomains": true, "mode": "force-https" }, + { "name": "demuzere.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "docucopies.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "elmermx.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "extreemhost.nl", "include_subdomains": true, "mode": "force-https" }, + { "name": "fabianasantiago.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "gamers-life.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "globalinstitutefortraining.org.au", "include_subdomains": true, "mode": "force-https" }, + { "name": "graingert.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "greenvines.com.tw", "include_subdomains": true, "mode": "force-https" }, + { "name": "hao2taiwan.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "hollowrap.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "hostanalyticsconsulting.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "hostingactive.it", "include_subdomains": true, "mode": "force-https" }, + { "name": "humankode.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "immunicity.info", "include_subdomains": true, "mode": "force-https" }, + { "name": "kahopoon.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "khetzal.info", "include_subdomains": true, "mode": "force-https" }, + { "name": "koerperimpuls.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "lostinsecurity.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "mailinabox.email", "include_subdomains": true, "mode": "force-https" }, + { "name": "malash.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "masjidtawheed.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "newodesign.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "nicolaelmer.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "ochsundjunior.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "onixcco.com.br", "include_subdomains": true, "mode": "force-https" }, + { "name": "pctonic.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "photoblogverona.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "pluga.co", "include_subdomains": true, "mode": "force-https" }, + { "name": "prefis.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "prepandgo-euro.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "production.vn", "include_subdomains": true, "mode": "force-https" }, + { "name": "raconconsulting.co.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "rangde.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "remotestance.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "renuo.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "riskmitigation.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "sanhei.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "scaling.solutions", "include_subdomains": true, "mode": "force-https" }, + { "name": "sifls.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "smkn1lengkong.sch.id", "include_subdomains": true, "mode": "force-https" }, + { "name": "ssldecoder.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "startupsort.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "sx3.no", "include_subdomains": true, "mode": "force-https" }, + { "name": "tech-seminar.jp", "include_subdomains": true, "mode": "force-https" }, + { "name": "tncnanet.com.br", "include_subdomains": true, "mode": "force-https" }, + { "name": "tomo.gr", "include_subdomains": true, "mode": "force-https" }, + { "name": "utilia.tools", "include_subdomains": true, "mode": "force-https" }, + { "name": "viewmyrecords.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "www.vino75.com", "include_subdomains": false, "mode": "force-https" }, + { "name": "vmrdev.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "vulnerability.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "xiaolan.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "xiaoxiao.im", "include_subdomains": true, "mode": "force-https" }, + { "name": "hana.ondemand.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "fastmail.com", "mode": "force-https" }, + { "name": "www.fastmail.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "3chit.cf", "include_subdomains": true, "mode": "force-https" }, + { "name": "777coin.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ad-notam.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ad-notam.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "ad-notam.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "ad-notam.it", "include_subdomains": true, "mode": "force-https" }, + { "name": "ad-notam.us", "include_subdomains": true, "mode": "force-https" }, + { "name": "adhs-chaoten.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "ageg.ca", "include_subdomains": true, "mode": "force-https" }, + { "name": "alpca.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "americanbio.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "amoory.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "appmobile.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "attotech.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "aussiecable.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "avarty.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "aylak.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "benny003.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "berthabailey.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "bexit.nl", "include_subdomains": true, "mode": "force-https" }, + { "name": "bitminter.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "blognone.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "borchers-media.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "bqtoolbox.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "burningcrash.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "capriccio.to", "include_subdomains": true, "mode": "force-https" }, + { "name": "certifi.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "clycat.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "cogumelosmagicos.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "connect.ua", "include_subdomains": true, "mode": "force-https" }, + { "name": "cryptobells.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "csfs.org.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "cspvalidator.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "cubewano.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "deepcovelabs.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "deliciisanatoase.ro", "include_subdomains": true, "mode": "force-https" }, + { "name": "dienstplan.one", "include_subdomains": true, "mode": "force-https" }, + { "name": "drbethanybarnes.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "eddmixpanel.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ehipaa.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ehipaadev.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "emanuelduss.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "enjen.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "envygeeks.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "envygeeks.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "fayolle.info", "include_subdomains": true, "mode": "force-https" }, + { "name": "flirchi.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "fuglede.dk", "include_subdomains": true, "mode": "force-https" }, + { "name": "gc-mc.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "gcs-ventures.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "gerencianet.com.br", "include_subdomains": true, "mode": "force-https" }, + { "name": "gfournier.ca", "include_subdomains": true, "mode": "force-https" }, + { "name": "gotech.com.eg", "include_subdomains": true, "mode": "force-https" }, + { "name": "gyboche.science", "include_subdomains": true, "mode": "force-https" }, + { "name": "hackenturet.dk", "include_subdomains": true, "mode": "force-https" }, + { "name": "harmoney.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "istheapplestoredown.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "jayblock.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "jgid.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "juergenhecht.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "kpvpn.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "labrador-retrievers.com.au", "include_subdomains": true, "mode": "force-https" }, + { "name": "labradorpuppiesforsalebyregisteredlabradorbreeders.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "logement-saisonnier.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "lovingearth.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "mareklecian.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "maximilian-greger.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "mb-is.info", "include_subdomains": true, "mode": "force-https" }, + { "name": "mbdb.jp", "include_subdomains": true, "mode": "force-https" }, + { "name": "minecraftforum.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "mobile.eti.br", "include_subdomains": true, "mode": "force-https" }, + { "name": "mosstier.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "motd.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "mysecretcase.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "namorico.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "natukusa.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "nekomimi.pl", "include_subdomains": true, "mode": "force-https" }, + { "name": "netprofile.com.au", "include_subdomains": true, "mode": "force-https" }, + { "name": "numericacu.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "oshayr.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ourevents.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "overkillshop.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "pantsu.cat", "include_subdomains": true, "mode": "force-https" }, + { "name": "paylike.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "peifi.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "pennylane.me.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "petko.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "pfd-nz.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "pirati.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "plirt.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "qgustavor.tk", "include_subdomains": true, "mode": "force-https" }, + { "name": "rentinsingapore.com.sg", "include_subdomains": true, "mode": "force-https" }, + { "name": "rideworks.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "riesenweber.id.au", "include_subdomains": true, "mode": "force-https" }, + { "name": "rivy.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "robi-net.it", "include_subdomains": true, "mode": "force-https" }, + { "name": "rootservice.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "sanasport.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "si-benelux.nl", "include_subdomains": true, "mode": "force-https" }, + { "name": "simplednscrypt.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "smartmessages.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "smksi2.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "snapappointments.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "southernutahinfluencers.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "staack.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "stackptr.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "stinkytrashhound.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "stugb.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "sunflyer.cn", "include_subdomains": true, "mode": "force-https" }, + { "name": "swapadoodle.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "syncer.jp", "include_subdomains": true, "mode": "force-https" }, + { "name": "tannenhof-moelln.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "theintercept.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "thinklikeanentrepreneur.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ulabox.cat", "include_subdomains": true, "mode": "force-https" }, + { "name": "ulabox.es", "include_subdomains": true, "mode": "force-https" }, + { "name": "umgardi.ca", "include_subdomains": true, "mode": "force-https" }, + { "name": "upay.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "upstats.eu", "include_subdomains": true, "mode": "force-https" }, + { "name": "usgande.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "vat-eu.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "veblen.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "viemeister.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "voliere-info.nl", "include_subdomains": true, "mode": "force-https" }, + { "name": "wait.jp", "include_subdomains": true, "mode": "force-https" }, + { "name": "wdesk.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "wohnsitz-ausland.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "woima.fi", "include_subdomains": true, "mode": "force-https" }, + { "name": "wolfemg.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "wrldevelopment.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "xiaody.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "xn--t8j4aa4nyhxa7duezbl49aqg5546e264d.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "xtremegaming.it", "include_subdomains": true, "mode": "force-https" }, + { "name": "xunn.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "zdrojak.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "zera.com.au", "include_subdomains": true, "mode": "force-https" }, + { "name": "0xfc.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "abrilect.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "adduono.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ahmerjamilkhan.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "akombakom.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "alainwolf.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "aulo.in", "include_subdomains": true, "mode": "force-https" }, + { "name": "beier.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "bentrask.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "bryn.xyz", "include_subdomains": true, "mode": "force-https" }, + { "name": "cavac.at", "include_subdomains": true, "mode": "force-https" }, + { "name": "cipherli.st", "include_subdomains": true, "mode": "force-https" }, + { "name": "claralabs.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "coolaj86.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "coralproject.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "crosscom.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "curroapp.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "daplie.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "darknebula.space", "include_subdomains": true, "mode": "force-https" }, + { "name": "datapun.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "datsound.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "devlux.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "ellsinger.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "excessamerica.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "express-vpn.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "felixrr.pro", "include_subdomains": true, "mode": "force-https" }, + { "name": "filippo.io", "include_subdomains": true, "mode": "force-https" }, + { "name": "flowlo.me", "include_subdomains": true, "mode": "force-https" }, + { "name": "flukethoughts.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "fraye.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "freedom.press", "include_subdomains": true, "mode": "force-https" }, + { "name": "fresh-hotel.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "goaltree.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "goldenhillsoftware.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "greenpeace-magazin.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "guineapigmustach.es", "include_subdomains": true, "mode": "force-https" }, + { "name": "htaccessbook.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "isitup.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "kaloix.de", "include_subdomains": true, "mode": "force-https" }, + { "name": "kiano.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "krypsys.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "lainchan.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "lazurit.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "lelongbank.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "lexway.pk", "include_subdomains": true, "mode": "force-https" }, + { "name": "libertyrp.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "lustrumxi.nl", "include_subdomains": true, "mode": "force-https" }, + { "name": "maderwin.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "mypagella.eu", "include_subdomains": true, "mode": "force-https" }, + { "name": "mypagella.it", "include_subdomains": true, "mode": "force-https" }, + { "name": "mysecretrewards.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "nettopower.dk", "include_subdomains": true, "mode": "force-https" }, + { "name": "nicestresser.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "nsboston.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "o7.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "onet.space", "include_subdomains": true, "mode": "force-https" }, + { "name": "oopsmycase.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "opennippon.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "opennippon.ru", "include_subdomains": true, "mode": "force-https" }, + { "name": "perishablepress.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "planboardapp.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "plugin-planet.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "qionglu.pw", "include_subdomains": true, "mode": "force-https" }, + { "name": "redb.cz", "include_subdomains": true, "mode": "force-https" }, + { "name": "rootforum.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "sambeso.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "sarasturdivant.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "scourt.org.ua", "include_subdomains": true, "mode": "force-https" }, + { "name": "secure-games.us", "include_subdomains": true, "mode": "force-https" }, + { "name": "selecadm.name", "include_subdomains": true, "mode": "force-https" }, + { "name": "sirenslove.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "smm.im", "include_subdomains": true, "mode": "force-https" }, + { "name": "stassi.ch", "include_subdomains": true, "mode": "force-https" }, + { "name": "stephenandburns.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "sway-cdn.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "sway.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "thinkindifferent.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "tunnelblick.net", "include_subdomains": true, "mode": "force-https" }, + { "name": "typing.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "ufotable.uk", "include_subdomains": true, "mode": "force-https" }, + { "name": "up1.ca", "include_subdomains": true, "mode": "force-https" }, + { "name": "vermontcareergateway.org", "include_subdomains": true, "mode": "force-https" }, + { "name": "virtualsanity.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "whatsmychaincert.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "wjglerum.nl", "include_subdomains": true, "mode": "force-https" }, + { "name": "wp-tao.com", "include_subdomains": true, "mode": "force-https" }, + { "name": "yoloprod.fr", "include_subdomains": true, "mode": "force-https" }, + { "name": "zzsec.org", "include_subdomains": true, "mode": "force-https" } ], // |ReportUMAOnPinFailure| uses these to report which domain was associated @@ -3390,6 +4120,12 @@ "CHROME_COM", "GVT3_COM", "GVT2_COM", - "GOOGLE" + "GOOGLE", + "GGPHT_COM", + "BLOGSPOT_COM", + "DROPBOXSTATIC_COM", + "DROPBOXUSERCONTENT_COM", + "WITHYOUTUBE_COM", + "WITHGOOGLE_COM" ] } diff --git a/chromium/net/http/transport_security_state_unittest.cc b/chromium/net/http/transport_security_state_unittest.cc index 3b9bf7b96a8..96d6231f5cc 100644 --- a/chromium/net/http/transport_security_state_unittest.cc +++ b/chromium/net/http/transport_security_state_unittest.cc @@ -10,10 +10,13 @@ #include "base/base64.h" #include "base/files/file_path.h" +#include "base/json/json_reader.h" #include "base/rand_util.h" #include "base/sha1.h" #include "base/strings/string_piece.h" +#include "base/values.h" #include "crypto/sha2.h" +#include "net/base/host_port_pair.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/base/test_data_directory.h" @@ -37,6 +40,139 @@ namespace net { +namespace { + +const char kHost[] = "example.test"; +const char kSubdomain[] = "foo.example.test"; +const uint16_t kPort = 443; +const char kReportUri[] = "http://report-example.test/test"; + +// kGoodPath is blog.torproject.org. +const char* const kGoodPath[] = { + "sha1/Yz4vayd/83rQfDXkDPn2yhzIScw=", + "sha1/3lKvjNsfmrn+WmfDhvr2iVh/yRs=", + "sha1/gzF+YoVCU9bXeDGQ7JGQVumRueM=", + "sha256/4osU79hfY3P2+WJGlT2mxmSL+5FIwLEVxTQcavyBNgQ=", + "sha256/k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws=", + "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=", + nullptr, +}; + +const char kGoodPin1[] = "4osU79hfY3P2+WJGlT2mxmSL+5FIwLEVxTQcavyBNgQ="; +const char kGoodPin2[] = "k2v657xBsOVe1PQRwOsHsw3bsGT2VzIqz5K+59sNQws="; +const char kGoodPin3[] = "WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18="; + +// kBadPath is plus.google.com via Trustcenter, which is utterly wrong for +// torproject.org. +const char* const kBadPath[] = { + "sha1/111111111111111111111111111=", + "sha1/222222222222222222222222222=", + "sha1/333333333333333333333333333=", + "sha256/1111111111111111111111111111111111111111111=", + "sha256/2222222222222222222222222222222222222222222=", + "sha256/3333333333333333333333333333333333333333333=", + nullptr, +}; + +// A mock ReportSender that just remembers the latest report +// URI and report to be sent. +class MockCertificateReportSender + : public TransportSecurityState::ReportSender { + public: + MockCertificateReportSender() {} + ~MockCertificateReportSender() override {} + + void Send(const GURL& report_uri, const std::string& report) override { + latest_report_uri_ = report_uri; + latest_report_ = report; + } + + void Clear() { + latest_report_uri_ = GURL(); + latest_report_ = std::string(); + } + + const GURL& latest_report_uri() { return latest_report_uri_; } + const std::string& latest_report() { return latest_report_; } + + private: + GURL latest_report_uri_; + std::string latest_report_; +}; + +void CompareCertificateChainWithList( + const scoped_refptr<X509Certificate>& cert_chain, + const base::ListValue* cert_list) { + ASSERT_TRUE(cert_chain); + std::vector<std::string> pem_encoded_chain; + cert_chain->GetPEMEncodedChain(&pem_encoded_chain); + EXPECT_EQ(pem_encoded_chain.size(), cert_list->GetSize()); + + for (size_t i = 0; i < pem_encoded_chain.size(); i++) { + std::string list_cert; + ASSERT_TRUE(cert_list->GetString(i, &list_cert)); + EXPECT_EQ(pem_encoded_chain[i], list_cert); + } +} + +void CheckHPKPReport( + const std::string& report, + const HostPortPair& host_port_pair, + bool include_subdomains, + const std::string& noted_hostname, + const scoped_refptr<X509Certificate>& served_certificate_chain, + const scoped_refptr<X509Certificate>& validated_certificate_chain, + const HashValueVector& known_pins) { + scoped_ptr<base::Value> value(base::JSONReader::Read(report)); + ASSERT_TRUE(value); + ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY)); + + base::DictionaryValue* report_dict; + ASSERT_TRUE(value->GetAsDictionary(&report_dict)); + + std::string report_hostname; + EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname)); + EXPECT_EQ(host_port_pair.host(), report_hostname); + + int report_port; + EXPECT_TRUE(report_dict->GetInteger("port", &report_port)); + EXPECT_EQ(host_port_pair.port(), report_port); + + bool report_include_subdomains; + EXPECT_TRUE(report_dict->GetBoolean("include-subdomains", + &report_include_subdomains)); + EXPECT_EQ(include_subdomains, report_include_subdomains); + + std::string report_noted_hostname; + EXPECT_TRUE(report_dict->GetString("noted-hostname", &report_noted_hostname)); + EXPECT_EQ(noted_hostname, report_noted_hostname); + + // TODO(estark): check times in RFC3339 format. + + std::string report_expiration; + EXPECT_TRUE( + report_dict->GetString("effective-expiration-date", &report_expiration)); + EXPECT_FALSE(report_expiration.empty()); + + std::string report_date; + EXPECT_TRUE(report_dict->GetString("date-time", &report_date)); + EXPECT_FALSE(report_date.empty()); + + base::ListValue* report_served_certificate_chain; + EXPECT_TRUE(report_dict->GetList("served-certificate-chain", + &report_served_certificate_chain)); + ASSERT_NO_FATAL_FAILURE(CompareCertificateChainWithList( + served_certificate_chain, report_served_certificate_chain)); + + base::ListValue* report_validated_certificate_chain; + EXPECT_TRUE(report_dict->GetList("validated-certificate-chain", + &report_validated_certificate_chain)); + ASSERT_NO_FATAL_FAILURE(CompareCertificateChainWithList( + validated_certificate_chain, report_validated_certificate_chain)); +} + +} // namespace + class TransportSecurityStateTest : public testing::Test { public: void SetUp() override { @@ -57,7 +193,7 @@ class TransportSecurityStateTest : public testing::Test { static HashValueVector GetSampleSPKIHashes() { HashValueVector spki_hashes; - HashValue hash(HASH_VALUE_SHA1); + HashValue hash(HASH_VALUE_SHA256); memset(hash.data(), 0, hash.size()); spki_hashes.push_back(hash); return spki_hashes; @@ -214,6 +350,7 @@ TEST_F(TransportSecurityStateTest, SubdomainMatches) { // with it, regardless of the includeSubDomains bit. This is a regression test // for https://crbug.com/469957. TEST_F(TransportSecurityStateTest, SubdomainCarveout) { + const GURL report_uri(kReportUri); TransportSecurityState state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); @@ -222,8 +359,10 @@ TEST_F(TransportSecurityStateTest, SubdomainCarveout) { state.AddHSTS("example1.test", expiry, true); state.AddHSTS("foo.example1.test", expiry, false); - state.AddHPKP("example2.test", expiry, true, GetSampleSPKIHashes()); - state.AddHPKP("foo.example2.test", expiry, false, GetSampleSPKIHashes()); + state.AddHPKP("example2.test", expiry, true, GetSampleSPKIHashes(), + report_uri); + state.AddHPKP("foo.example2.test", expiry, false, GetSampleSPKIHashes(), + report_uri); EXPECT_TRUE(state.ShouldUpgradeToSSL("example1.test")); EXPECT_TRUE(state.ShouldUpgradeToSSL("foo.example1.test")); @@ -243,7 +382,8 @@ TEST_F(TransportSecurityStateTest, SubdomainCarveout) { // Expire the foo.example*.test rules. state.AddHSTS("foo.example1.test", older, false); - state.AddHPKP("foo.example2.test", older, false, GetSampleSPKIHashes()); + state.AddHPKP("foo.example2.test", older, false, GetSampleSPKIHashes(), + report_uri); // Now the base example*.test rules apply to bar.foo.example*.test. EXPECT_TRUE(state.ShouldUpgradeToSSL("bar.foo.example1.test")); @@ -253,12 +393,14 @@ TEST_F(TransportSecurityStateTest, SubdomainCarveout) { } TEST_F(TransportSecurityStateTest, FatalSSLErrors) { + const GURL report_uri(kReportUri); TransportSecurityState state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); state.AddHSTS("example1.test", expiry, false); - state.AddHPKP("example2.test", expiry, false, GetSampleSPKIHashes()); + state.AddHPKP("example2.test", expiry, false, GetSampleSPKIHashes(), + report_uri); // The presense of either HSTS or HPKP is enough to make SSL errors fatal. EXPECT_TRUE(state.ShouldSSLErrorsBeFatal("example1.test")); @@ -268,6 +410,7 @@ TEST_F(TransportSecurityStateTest, FatalSSLErrors) { // Tests that HPKP and HSTS state both expire. Also tests that expired entries // are pruned. TEST_F(TransportSecurityStateTest, Expiration) { + const GURL report_uri(kReportUri); TransportSecurityState state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); @@ -281,14 +424,16 @@ TEST_F(TransportSecurityStateTest, Expiration) { // Querying |state| for a domain should flush out expired entries. EXPECT_FALSE(TransportSecurityState::STSStateIterator(state).HasNext()); - state.AddHPKP("example1.test", older, false, GetSampleSPKIHashes()); + state.AddHPKP("example1.test", older, false, GetSampleSPKIHashes(), + report_uri); EXPECT_TRUE(TransportSecurityState::PKPStateIterator(state).HasNext()); EXPECT_FALSE(state.HasPublicKeyPins("example1.test")); // Querying |state| for a domain should flush out expired entries. EXPECT_FALSE(TransportSecurityState::PKPStateIterator(state).HasNext()); state.AddHSTS("example1.test", older, false); - state.AddHPKP("example1.test", older, false, GetSampleSPKIHashes()); + state.AddHPKP("example1.test", older, false, GetSampleSPKIHashes(), + report_uri); EXPECT_TRUE(TransportSecurityState::STSStateIterator(state).HasNext()); EXPECT_TRUE(TransportSecurityState::PKPStateIterator(state).HasNext()); EXPECT_FALSE(state.ShouldSSLErrorsBeFatal("example1.test")); @@ -298,13 +443,15 @@ TEST_F(TransportSecurityStateTest, Expiration) { // Test that HSTS can outlive HPKP. state.AddHSTS("example1.test", expiry, false); - state.AddHPKP("example1.test", older, false, GetSampleSPKIHashes()); + state.AddHPKP("example1.test", older, false, GetSampleSPKIHashes(), + report_uri); EXPECT_TRUE(state.ShouldUpgradeToSSL("example1.test")); EXPECT_FALSE(state.HasPublicKeyPins("example1.test")); // Test that HPKP can outlive HSTS. state.AddHSTS("example2.test", older, false); - state.AddHPKP("example2.test", expiry, false, GetSampleSPKIHashes()); + state.AddHPKP("example2.test", expiry, false, GetSampleSPKIHashes(), + report_uri); EXPECT_FALSE(state.ShouldUpgradeToSSL("example2.test")); EXPECT_TRUE(state.HasPublicKeyPins("example2.test")); } @@ -324,15 +471,18 @@ TEST_F(TransportSecurityStateTest, InvalidDomains) { // Tests that HPKP and HSTS state are queried independently for subdomain // matches. TEST_F(TransportSecurityStateTest, IndependentSubdomain) { + const GURL report_uri(kReportUri); TransportSecurityState state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); state.AddHSTS("example1.test", expiry, true); - state.AddHPKP("example1.test", expiry, false, GetSampleSPKIHashes()); + state.AddHPKP("example1.test", expiry, false, GetSampleSPKIHashes(), + report_uri); state.AddHSTS("example2.test", expiry, false); - state.AddHPKP("example2.test", expiry, true, GetSampleSPKIHashes()); + state.AddHPKP("example2.test", expiry, true, GetSampleSPKIHashes(), + report_uri); EXPECT_TRUE(state.ShouldUpgradeToSSL("foo.example1.test")); EXPECT_FALSE(state.HasPublicKeyPins("foo.example1.test")); @@ -342,13 +492,15 @@ TEST_F(TransportSecurityStateTest, IndependentSubdomain) { // Tests that HPKP and HSTS state are inserted and overridden independently. TEST_F(TransportSecurityStateTest, IndependentInsertion) { + const GURL report_uri(kReportUri); TransportSecurityState state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); // Place an includeSubdomains HSTS entry below a normal HPKP entry. state.AddHSTS("example1.test", expiry, true); - state.AddHPKP("foo.example1.test", expiry, false, GetSampleSPKIHashes()); + state.AddHPKP("foo.example1.test", expiry, false, GetSampleSPKIHashes(), + report_uri); EXPECT_TRUE(state.ShouldUpgradeToSSL("foo.example1.test")); EXPECT_TRUE(state.HasPublicKeyPins("foo.example1.test")); @@ -363,13 +515,15 @@ TEST_F(TransportSecurityStateTest, IndependentInsertion) { // Place an includeSubdomains HPKP entry below a normal HSTS entry. state.AddHSTS("foo.example2.test", expiry, false); - state.AddHPKP("example2.test", expiry, true, GetSampleSPKIHashes()); + state.AddHPKP("example2.test", expiry, true, GetSampleSPKIHashes(), + report_uri); EXPECT_TRUE(state.ShouldUpgradeToSSL("foo.example2.test")); EXPECT_TRUE(state.HasPublicKeyPins("foo.example2.test")); // Drop the includeSubdomains from the HSTS entry. - state.AddHPKP("example2.test", expiry, false, GetSampleSPKIHashes()); + state.AddHPKP("example2.test", expiry, false, GetSampleSPKIHashes(), + report_uri); EXPECT_TRUE(state.ShouldUpgradeToSSL("foo.example2.test")); EXPECT_FALSE(state.HasPublicKeyPins("foo.example2.test")); @@ -378,13 +532,15 @@ TEST_F(TransportSecurityStateTest, IndependentInsertion) { // Tests that GetDynamic[PKP|STS]State returns the correct data and that the // states are not mixed together. TEST_F(TransportSecurityStateTest, DynamicDomainState) { + const GURL report_uri(kReportUri); TransportSecurityState state; const base::Time current_time(base::Time::Now()); const base::Time expiry1 = current_time + base::TimeDelta::FromSeconds(1000); const base::Time expiry2 = current_time + base::TimeDelta::FromSeconds(2000); state.AddHSTS("example.com", expiry1, true); - state.AddHPKP("foo.example.com", expiry2, false, GetSampleSPKIHashes()); + state.AddHPKP("foo.example.com", expiry2, false, GetSampleSPKIHashes(), + report_uri); TransportSecurityState::STSState sts_state; TransportSecurityState::PKPState pkp_state; @@ -403,30 +559,34 @@ TEST_F(TransportSecurityStateTest, DynamicDomainState) { // Tests that new pins always override previous pins. This should be true for // both pins at the same domain or includeSubdomains pins at a parent domain. TEST_F(TransportSecurityStateTest, NewPinsOverride) { + const GURL report_uri(kReportUri); TransportSecurityState state; TransportSecurityState::PKPState pkp_state; const base::Time current_time(base::Time::Now()); const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); - HashValue hash1(HASH_VALUE_SHA1); + HashValue hash1(HASH_VALUE_SHA256); memset(hash1.data(), 0x01, hash1.size()); - HashValue hash2(HASH_VALUE_SHA1); + HashValue hash2(HASH_VALUE_SHA256); memset(hash2.data(), 0x02, hash1.size()); - HashValue hash3(HASH_VALUE_SHA1); + HashValue hash3(HASH_VALUE_SHA256); memset(hash3.data(), 0x03, hash1.size()); - state.AddHPKP("example.com", expiry, true, HashValueVector(1, hash1)); + state.AddHPKP("example.com", expiry, true, HashValueVector(1, hash1), + report_uri); ASSERT_TRUE(state.GetDynamicPKPState("foo.example.com", &pkp_state)); ASSERT_EQ(1u, pkp_state.spki_hashes.size()); EXPECT_TRUE(pkp_state.spki_hashes[0].Equals(hash1)); - state.AddHPKP("foo.example.com", expiry, false, HashValueVector(1, hash2)); + state.AddHPKP("foo.example.com", expiry, false, HashValueVector(1, hash2), + report_uri); ASSERT_TRUE(state.GetDynamicPKPState("foo.example.com", &pkp_state)); ASSERT_EQ(1u, pkp_state.spki_hashes.size()); EXPECT_TRUE(pkp_state.spki_hashes[0].Equals(hash2)); - state.AddHPKP("foo.example.com", expiry, false, HashValueVector(1, hash3)); + state.AddHPKP("foo.example.com", expiry, false, HashValueVector(1, hash3), + report_uri); ASSERT_TRUE(state.GetDynamicPKPState("foo.example.com", &pkp_state)); ASSERT_EQ(1u, pkp_state.spki_hashes.size()); @@ -444,7 +604,7 @@ TEST_F(TransportSecurityStateTest, DeleteAllDynamicDataSince) { bool include_subdomains = false; state.AddHSTS("example.com", expiry, include_subdomains); state.AddHPKP("example.com", expiry, include_subdomains, - GetSampleSPKIHashes()); + GetSampleSPKIHashes(), GURL()); state.DeleteAllDynamicDataSince(expiry); EXPECT_TRUE(state.ShouldUpgradeToSSL("example.com")); @@ -466,7 +626,7 @@ TEST_F(TransportSecurityStateTest, DeleteDynamicDataForHost) { state.AddHSTS("example1.test", expiry, include_subdomains); state.AddHPKP("example1.test", expiry, include_subdomains, - GetSampleSPKIHashes()); + GetSampleSPKIHashes(), GURL()); EXPECT_TRUE(state.ShouldUpgradeToSSL("example1.test")); EXPECT_FALSE(state.ShouldUpgradeToSSL("example2.test")); @@ -940,23 +1100,6 @@ static bool AddHash(const std::string& type_and_base64, } TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) { - // kGoodPath is blog.torproject.org. - static const char* const kGoodPath[] = { - "sha1/m9lHYJYke9k0GtVZ+bXSQYE8nDI=", - "sha1/o5OZxATDsgmwgcIfIWIneMJ0jkw=", - "sha1/wHqYaI2J+6sFZAwRfap9ZbjKzE4=", - NULL, - }; - - // kBadPath is plus.google.com via Trustcenter, which is utterly wrong for - // torproject.org. - static const char* const kBadPath[] = { - "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=", - "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=", - "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=", - NULL, - }; - HashValueVector good_hashes, bad_hashes; for (size_t i = 0; kGoodPath[i]; i++) { @@ -1082,4 +1225,317 @@ TEST_F(TransportSecurityStateTest, GooglePinnedProperties) { "www.googlegroups.com")); } +TEST_F(TransportSecurityStateTest, HPKPReporting) { + HostPortPair host_port_pair(kHost, kPort); + HostPortPair subdomain_host_port_pair(kSubdomain, kPort); + GURL report_uri(kReportUri); + // Two dummy certs to use as the server-sent and validated chains. The + // contents don't matter. + scoped_refptr<X509Certificate> cert1 = + ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); + scoped_refptr<X509Certificate> cert2 = + ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem"); + ASSERT_TRUE(cert1); + ASSERT_TRUE(cert2); + + HashValueVector good_hashes, bad_hashes; + + for (size_t i = 0; kGoodPath[i]; i++) + EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes)); + for (size_t i = 0; kBadPath[i]; i++) + EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes)); + + TransportSecurityState state; + MockCertificateReportSender mock_report_sender; + state.SetReportSender(&mock_report_sender); + + const base::Time current_time = base::Time::Now(); + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); + state.AddHPKP(kHost, expiry, true, good_hashes, report_uri); + + EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri()); + EXPECT_EQ(std::string(), mock_report_sender.latest_report()); + + std::string failure_log; + EXPECT_FALSE(state.CheckPublicKeyPins( + host_port_pair, true, bad_hashes, cert1.get(), cert2.get(), + TransportSecurityState::DISABLE_PIN_REPORTS, &failure_log)); + + // No report should have been sent because of the DISABLE_PIN_REPORTS + // argument. + EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri()); + EXPECT_EQ(std::string(), mock_report_sender.latest_report()); + + EXPECT_TRUE(state.CheckPublicKeyPins( + host_port_pair, true, good_hashes, cert1.get(), cert2.get(), + TransportSecurityState::ENABLE_PIN_REPORTS, &failure_log)); + + // No report should have been sent because there was no violation. + EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri()); + EXPECT_EQ(std::string(), mock_report_sender.latest_report()); + + EXPECT_FALSE(state.CheckPublicKeyPins( + host_port_pair, true, bad_hashes, cert1.get(), cert2.get(), + TransportSecurityState::ENABLE_PIN_REPORTS, &failure_log)); + + // Now a report should have been sent. Check that it contains the + // right information. + EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri()); + std::string report = mock_report_sender.latest_report(); + ASSERT_FALSE(report.empty()); + ASSERT_NO_FATAL_FAILURE(CheckHPKPReport(report, host_port_pair, true, kHost, + cert1.get(), cert2.get(), + good_hashes)); + mock_report_sender.Clear(); + EXPECT_FALSE(state.CheckPublicKeyPins( + subdomain_host_port_pair, true, bad_hashes, cert1.get(), cert2.get(), + TransportSecurityState::ENABLE_PIN_REPORTS, &failure_log)); + + // Now a report should have been sent for the subdomain. Check that it + // contains the right information. + EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri()); + report = mock_report_sender.latest_report(); + ASSERT_FALSE(report.empty()); + ASSERT_NO_FATAL_FAILURE(CheckHPKPReport(report, subdomain_host_port_pair, + true, kHost, cert1.get(), cert2.get(), + good_hashes)); +} + +TEST_F(TransportSecurityStateTest, HPKPReportOnly) { + HostPortPair host_port_pair(kHost, kPort); + GURL report_uri(kReportUri); + // Two dummy certs to use as the server-sent and validated chains. The + // contents don't matter. + scoped_refptr<X509Certificate> cert1 = + ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); + scoped_refptr<X509Certificate> cert2 = + ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem"); + ASSERT_TRUE(cert1); + ASSERT_TRUE(cert2); + + TransportSecurityState state; + MockCertificateReportSender mock_report_sender; + state.SetReportSender(&mock_report_sender); + + // Check that a report is not sent for a Report-Only header with no + // violation. + std::string header = + "pin-sha256=\"" + std::string(kGoodPin1) + "\";pin-sha256=\"" + + std::string(kGoodPin2) + "\";pin-sha256=\"" + std::string(kGoodPin3) + + "\";report-uri=\"" + report_uri.spec() + "\";includeSubdomains"; + SSLInfo ssl_info; + ssl_info.is_issued_by_known_root = true; + ssl_info.unverified_cert = cert1; + ssl_info.cert = cert2; + for (size_t i = 0; kGoodPath[i]; i++) + EXPECT_TRUE(AddHash(kGoodPath[i], &ssl_info.public_key_hashes)); + + EXPECT_TRUE( + state.ProcessHPKPReportOnlyHeader(header, host_port_pair, ssl_info)); + EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri()); + EXPECT_EQ(std::string(), mock_report_sender.latest_report()); + + // Check that a report is sent for a Report-Only header with a + // violation. + ssl_info.public_key_hashes.clear(); + for (size_t i = 0; kBadPath[i]; i++) + EXPECT_TRUE(AddHash(kBadPath[i], &ssl_info.public_key_hashes)); + + EXPECT_TRUE( + state.ProcessHPKPReportOnlyHeader(header, host_port_pair, ssl_info)); + EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri()); + std::string report = mock_report_sender.latest_report(); + ASSERT_FALSE(report.empty()); + ASSERT_NO_FATAL_FAILURE(CheckHPKPReport(report, host_port_pair, true, kHost, + cert1.get(), cert2.get(), + ssl_info.public_key_hashes)); + + // HTTPS report URIs on the same host as the pin violation should not + // be allowed, to avoid going into a report-sending loop. + mock_report_sender.Clear(); + header = "pin-sha256=\"" + std::string(kGoodPin1) + "\";pin-sha256=\"" + + std::string(kGoodPin2) + "\";pin-sha256=\"" + + std::string(kGoodPin3) + "\";report-uri=\"https://" + + host_port_pair.host() + "/report\";includeSubdomains"; + EXPECT_TRUE( + state.ProcessHPKPReportOnlyHeader(header, host_port_pair, ssl_info)); + EXPECT_TRUE(mock_report_sender.latest_report_uri().is_empty()); +} + +// Tests that Report-Only reports are not sent on certs that chain to +// local roots. +TEST_F(TransportSecurityStateTest, HPKPReportOnlyOnLocalRoot) { + HostPortPair host_port_pair(kHost, kPort); + GURL report_uri(kReportUri); + // Two dummy certs to use as the server-sent and validated chains. The + // contents don't matter. + scoped_refptr<X509Certificate> cert1 = + ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); + scoped_refptr<X509Certificate> cert2 = + ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem"); + ASSERT_TRUE(cert1); + ASSERT_TRUE(cert2); + + std::string header = + "pin-sha256=\"" + std::string(kGoodPin1) + "\";pin-sha256=\"" + + std::string(kGoodPin2) + "\";pin-sha256=\"" + std::string(kGoodPin3) + + "\";report-uri=\"" + report_uri.spec() + "\";includeSubdomains"; + + TransportSecurityState state; + MockCertificateReportSender mock_report_sender; + state.SetReportSender(&mock_report_sender); + + SSLInfo ssl_info; + ssl_info.is_issued_by_known_root = true; + ssl_info.unverified_cert = cert1; + ssl_info.cert = cert2; + for (size_t i = 0; kGoodPath[i]; i++) + EXPECT_TRUE(AddHash(kGoodPath[i], &ssl_info.public_key_hashes)); + ssl_info.is_issued_by_known_root = false; + + EXPECT_TRUE( + state.ProcessHPKPReportOnlyHeader(header, host_port_pair, ssl_info)); + EXPECT_EQ(GURL(), mock_report_sender.latest_report_uri()); + EXPECT_EQ(std::string(), mock_report_sender.latest_report()); +} + +// Tests that ProcessHPKPReportOnlyHeader() returns false if a report-uri +// wasn't specified or if the header fails to parse. +TEST_F(TransportSecurityStateTest, HPKPReportOnlyParseErrors) { + HostPortPair host_port_pair(kHost, kPort); + GURL report_uri(kReportUri); + // Two dummy certs to use as the server-sent and validated chains. The + // contents don't matter. + scoped_refptr<X509Certificate> cert1 = + ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); + scoped_refptr<X509Certificate> cert2 = + ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem"); + ASSERT_TRUE(cert1); + ASSERT_TRUE(cert2); + + std::string header = "pin-sha256=\"" + std::string(kGoodPin1) + + "\";pin-sha256=\"" + std::string(kGoodPin2) + + "\";pin-sha256=\"" + std::string(kGoodPin3) + "\""; + + TransportSecurityState state; + MockCertificateReportSender mock_report_sender; + state.SetReportSender(&mock_report_sender); + + SSLInfo ssl_info; + ssl_info.is_issued_by_known_root = true; + ssl_info.unverified_cert = cert1; + ssl_info.cert = cert2; + for (size_t i = 0; kGoodPath[i]; i++) + EXPECT_TRUE(AddHash(kGoodPath[i], &ssl_info.public_key_hashes)); + + EXPECT_FALSE( + state.ProcessHPKPReportOnlyHeader(header, host_port_pair, ssl_info)); + header += ";report-uri=\""; + EXPECT_FALSE( + state.ProcessHPKPReportOnlyHeader(header, host_port_pair, ssl_info)); +} + +// Tests that pinning violations on preloaded pins trigger reports when +// the preloaded pin contains a report URI. +TEST_F(TransportSecurityStateTest, PreloadedPKPReportUri) { + const char kPreloadedPinDomain[] = "www.google.com"; + const uint16_t kPort = 443; + HostPortPair host_port_pair(kPreloadedPinDomain, kPort); + + TransportSecurityState state; + MockCertificateReportSender mock_report_sender; + state.SetReportSender(&mock_report_sender); + + ASSERT_TRUE( + TransportSecurityState::IsGooglePinnedProperty(kPreloadedPinDomain)); + EnableStaticPins(&state); + + TransportSecurityState::PKPState pkp_state; + TransportSecurityState::STSState unused_sts_state; + ASSERT_TRUE(state.GetStaticDomainState(kPreloadedPinDomain, &unused_sts_state, + &pkp_state)); + + GURL report_uri = pkp_state.report_uri; + ASSERT_TRUE(report_uri.is_valid()); + ASSERT_FALSE(report_uri.is_empty()); + + // Two dummy certs to use as the server-sent and validated chains. The + // contents don't matter, as long as they are not the real google.com + // certs in the pins. + scoped_refptr<X509Certificate> cert1 = + ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); + scoped_refptr<X509Certificate> cert2 = + ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem"); + ASSERT_TRUE(cert1); + ASSERT_TRUE(cert2); + + HashValueVector bad_hashes; + for (size_t i = 0; kBadPath[i]; i++) + EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes)); + + // Trigger a violation and check that it sends a report. + std::string failure_log; + EXPECT_FALSE(state.CheckPublicKeyPins( + host_port_pair, true, bad_hashes, cert1.get(), cert2.get(), + TransportSecurityState::ENABLE_PIN_REPORTS, &failure_log)); + + EXPECT_EQ(report_uri, mock_report_sender.latest_report_uri()); + + std::string report = mock_report_sender.latest_report(); + ASSERT_FALSE(report.empty()); + ASSERT_NO_FATAL_FAILURE(CheckHPKPReport( + report, host_port_pair, pkp_state.include_subdomains, pkp_state.domain, + cert1.get(), cert2.get(), pkp_state.spki_hashes)); +} + +// Tests that report URIs are thrown out if they point to the same host, +// over HTTPS, for which a pin was violated. +TEST_F(TransportSecurityStateTest, HPKPReportUriToSameHost) { + HostPortPair host_port_pair(kHost, kPort); + GURL https_report_uri("https://example.test/report"); + GURL http_report_uri("http://example.test/report"); + TransportSecurityState state; + MockCertificateReportSender mock_report_sender; + state.SetReportSender(&mock_report_sender); + + const base::Time current_time = base::Time::Now(); + const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000); + HashValueVector good_hashes; + for (size_t i = 0; kGoodPath[i]; i++) + EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes)); + + // Two dummy certs to use as the server-sent and validated chains. The + // contents don't matter, as long as they are not the real google.com + // certs in the pins. + scoped_refptr<X509Certificate> cert1 = + ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); + scoped_refptr<X509Certificate> cert2 = + ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem"); + ASSERT_TRUE(cert1); + ASSERT_TRUE(cert2); + + HashValueVector bad_hashes; + for (size_t i = 0; kBadPath[i]; i++) + EXPECT_TRUE(AddHash(kBadPath[i], &bad_hashes)); + + state.AddHPKP(kHost, expiry, true, good_hashes, https_report_uri); + + // Trigger a violation and check that it does not send a report + // because the report-uri is HTTPS and same-host as the pins. + std::string failure_log; + EXPECT_FALSE(state.CheckPublicKeyPins( + host_port_pair, true, bad_hashes, cert1.get(), cert2.get(), + TransportSecurityState::ENABLE_PIN_REPORTS, &failure_log)); + + EXPECT_TRUE(mock_report_sender.latest_report_uri().is_empty()); + + // An HTTP report uri to the same host should be okay. + state.AddHPKP("example.test", expiry, true, good_hashes, http_report_uri); + EXPECT_FALSE(state.CheckPublicKeyPins( + host_port_pair, true, bad_hashes, cert1.get(), cert2.get(), + TransportSecurityState::ENABLE_PIN_REPORTS, &failure_log)); + + EXPECT_EQ(http_report_uri, mock_report_sender.latest_report_uri()); +} + } // namespace net |