diff --git a/api/proto/teleport/legacy/types/events/events.proto b/api/proto/teleport/legacy/types/events/events.proto index 806875df1fe77..69369b9818384 100644 --- a/api/proto/teleport/legacy/types/events/events.proto +++ b/api/proto/teleport/legacy/types/events/events.proto @@ -4101,6 +4101,7 @@ message OneOf { events.ClusterNetworkingConfigUpdate ClusterNetworkingConfigUpdate = 154; events.DatabaseUserCreate DatabaseUserCreate = 155; events.DatabaseUserDeactivate DatabaseUserDeactivate = 156; + events.SpannerRPC SpannerRPC = 158; } } @@ -6159,3 +6160,44 @@ message SessionRecordingConfigUpdate { (gogoproto.jsontag) = "" ]; } + +// SpannerRPC is an event emitted when a Spanner client calls a Spanner RPC. +message SpannerRPC { + // Metadata is a common event metadata. + Metadata Metadata = 1 [ + (gogoproto.nullable) = false, + (gogoproto.embed) = true, + (gogoproto.jsontag) = "" + ]; + // User is a common user event metadata. + UserMetadata User = 2 [ + (gogoproto.nullable) = false, + (gogoproto.embed) = true, + (gogoproto.jsontag) = "" + ]; + // SessionMetadata is a common event session metadata. + SessionMetadata Session = 3 [ + (gogoproto.nullable) = false, + (gogoproto.embed) = true, + (gogoproto.jsontag) = "" + ]; + // Database contains database related metadata. + DatabaseMetadata Database = 4 [ + (gogoproto.nullable) = false, + (gogoproto.embed) = true, + (gogoproto.jsontag) = "" + ]; + // Status indicates whether the RPC was successfully sent to the database. + Status Status = 5 [ + (gogoproto.nullable) = false, + (gogoproto.embed) = true, + (gogoproto.jsontag) = "" + ]; + // Procedure is the name of the remote procedure. + string Procedure = 6 [(gogoproto.jsontag) = "procedure,omitempty"]; + // Args are the RPC arguments. + google.protobuf.Struct Args = 7 [ + (gogoproto.jsontag) = "args,omitempty", + (gogoproto.casttype) = "Struct" + ]; +} diff --git a/api/types/database.go b/api/types/database.go index a7723a0b9cae4..61888353e547a 100644 --- a/api/types/database.go +++ b/api/types/database.go @@ -30,6 +30,7 @@ import ( atlasutils "github.com/gravitational/teleport/api/utils/atlas" awsutils "github.com/gravitational/teleport/api/utils/aws" azureutils "github.com/gravitational/teleport/api/utils/azure" + gcputils "github.com/gravitational/teleport/api/utils/gcp" ) // Database represents a single database proxied by a database server. @@ -428,6 +429,11 @@ func (d *DatabaseV3) SetAWSAssumeRole(roleARN string) { d.Spec.AWS.AssumeRoleARN = roleARN } +// IsEmpty returns true if GCP metadata is empty. +func (g GCPCloudSQL) IsEmpty() bool { + return protoKnownFieldsEqual(&g, &GCPCloudSQL{}) +} + // GetGCP returns GCP information for Cloud SQL databases. func (d *DatabaseV3) GetGCP() GCPCloudSQL { return d.Spec.GCP @@ -506,6 +512,11 @@ func (d *DatabaseV3) IsOpenSearch() bool { return d.GetType() == DatabaseTypeOpenSearch } +// IsSpanner returns true if this is a GCloud Spanner database. +func (d *DatabaseV3) IsSpanner() bool { + return d.GetType() == DatabaseTypeSpanner +} + // IsAWSHosted returns true if database is hosted by AWS. func (d *DatabaseV3) IsAWSHosted() bool { _, ok := d.getAWSType() @@ -515,7 +526,7 @@ func (d *DatabaseV3) IsAWSHosted() bool { // IsCloudHosted returns true if database is hosted in the cloud (AWS, Azure or // Cloud SQL). func (d *DatabaseV3) IsCloudHosted() bool { - return d.IsAWSHosted() || d.IsCloudSQL() || d.IsAzure() + return d.IsAWSHosted() || d.IsGCPHosted() || d.IsAzure() } // GetCloud gets the cloud this database is running on, or an empty string if it @@ -524,7 +535,7 @@ func (d *DatabaseV3) GetCloud() string { switch { case d.IsAWSHosted(): return CloudAWS - case d.IsCloudSQL(): + case d.IsGCPHosted(): return CloudGCP case d.IsAzure(): return CloudAzure @@ -533,6 +544,24 @@ func (d *DatabaseV3) GetCloud() string { } } +// IsGCPHosted returns true if the database is hosted by GCP. +func (d *DatabaseV3) IsGCPHosted() bool { + _, ok := d.getGCPType() + return ok +} + +// getAWSType returns the gcp hosted database type. +func (d *DatabaseV3) getGCPType() (string, bool) { + if d.Spec.Protocol == DatabaseTypeSpanner { + return DatabaseTypeSpanner, true + } + gcp := d.GetGCP() + if !gcp.IsEmpty() { + return DatabaseTypeCloudSQL, true + } + return "", false +} + // getAWSType returns the database type. func (d *DatabaseV3) getAWSType() (string, bool) { aws := d.GetAWS() @@ -577,9 +606,10 @@ func (d *DatabaseV3) GetType() string { return awsType } - if d.GetGCP().ProjectID != "" { - return DatabaseTypeCloudSQL + if gcpType, ok := d.getGCPType(); ok { + return gcpType } + if d.GetAzure().Name != "" { return DatabaseTypeAzure } @@ -672,6 +702,9 @@ func (d *DatabaseV3) CheckAndSetDefaults() error { return trace.BadParameter("DynamoDB database %q URI is empty and cannot be derived without a configured AWS region", d.GetName()) } + case DatabaseTypeSpanner: + // All Spanner requests go to the same spanner google API endpoint. + d.Spec.URI = gcputils.SpannerEndpoint default: return trace.BadParameter("database %q URI is empty", d.GetName()) } @@ -684,6 +717,15 @@ func (d *DatabaseV3) CheckAndSetDefaults() error { // In case of RDS, Aurora or Redshift, AWS information such as region or // cluster ID can be extracted from the endpoint if not provided. switch { + case gcputils.IsSpannerEndpoint(d.Spec.URI) || d.IsSpanner(): + if d.Spec.GCP.ProjectID == "" { + return trace.BadParameter("GCP Spanner database %q missing GCP project ID", + d.GetName()) + } + if d.Spec.GCP.InstanceID == "" { + return trace.BadParameter("GCP Spanner database %q missing GCP instance ID", + d.GetName()) + } case d.IsDynamoDB(): if err := d.handleDynamoDBConfig(); err != nil { return trace.Wrap(err) @@ -1080,6 +1122,8 @@ const ( DatabaseTypeRedshiftServerless = "redshift-serverless" // DatabaseTypeCloudSQL is GCP-hosted Cloud SQL database. DatabaseTypeCloudSQL = "gcp" + // DatabaseTypeSpanner is a GCP Spanner instance. + DatabaseTypeSpanner = "spanner" // DatabaseTypeAzure is Azure-hosted database. DatabaseTypeAzure = "azure" // DatabaseTypeElastiCache is AWS-hosted ElastiCache database. diff --git a/api/types/database_test.go b/api/types/database_test.go index 41a5eabe651eb..aa9dd570ee96e 100644 --- a/api/types/database_test.go +++ b/api/types/database_test.go @@ -25,6 +25,8 @@ import ( "github.com/google/go-cmp/cmp/cmpopts" "github.com/gravitational/trace" "github.com/stretchr/testify/require" + + gcputils "github.com/gravitational/teleport/api/utils/gcp" ) // TestDatabaseRDSEndpoint verifies AWS info is correctly populated @@ -983,3 +985,82 @@ func TestIAMPolicyStatusJSON(t *testing.T) { require.NoError(t, status.UnmarshalJSON(data)) require.Equal(t, IAMPolicyStatus_IAM_POLICY_STATUS_FAILED, status) } + +func TestDatabaseSpanner(t *testing.T) { + t.Parallel() + + tests := map[string]struct { + spec DatabaseSpecV3 + errorCheck require.ErrorAssertionFunc + }{ + "valid with uri": { + spec: DatabaseSpecV3{ + Protocol: "spanner", + URI: gcputils.SpannerEndpoint, + GCP: GCPCloudSQL{ + ProjectID: "project-id", + InstanceID: "instance-id", + }, + }, + errorCheck: require.NoError, + }, + "valid without uri": { + spec: DatabaseSpecV3{ + Protocol: "spanner", + GCP: GCPCloudSQL{ + ProjectID: "project-id", + InstanceID: "instance-id", + }, + }, + errorCheck: require.NoError, + }, + "invalid missing project id": { + spec: DatabaseSpecV3{ + Protocol: "spanner", + GCP: GCPCloudSQL{ + InstanceID: "instance-id", + }, + }, + errorCheck: require.Error, + }, + "invalid missing instance id": { + spec: DatabaseSpecV3{ + Protocol: "spanner", + GCP: GCPCloudSQL{ + ProjectID: "project-id", + }, + }, + errorCheck: require.Error, + }, + "invalid missing project and instance id for spanner protocol": { + spec: DatabaseSpecV3{ + Protocol: "spanner", + }, + errorCheck: require.Error, + }, + "invalid missing project and instance id for spanner endpoint": { + spec: DatabaseSpecV3{ + URI: gcputils.SpannerEndpoint, + }, + errorCheck: require.Error, + }, + } + for name, test := range tests { + t.Run(name, func(t *testing.T) { + db, err := NewDatabaseV3( + Metadata{ + Name: "my-spanner", + }, + test.spec, + ) + test.errorCheck(t, err) + if err != nil { + return + } + + require.True(t, db.IsGCPHosted()) + require.Equal(t, DatabaseTypeSpanner, db.GetType()) + require.Equal(t, gcputils.SpannerEndpoint, db.GetURI()) + }) + } +} diff --git a/api/types/events/events.pb.go b/api/types/events/events.pb.go index 1e6b2c8a0a54e..8cb4b91f3106a 100644 --- a/api/types/events/events.pb.go +++ b/api/types/events/events.pb.go @@ -6917,6 +6917,7 @@ type OneOf struct { // *OneOf_ClusterNetworkingConfigUpdate // *OneOf_DatabaseUserCreate // *OneOf_DatabaseUserDeactivate + // *OneOf_SpannerRPC Event isOneOf_Event `protobuf_oneof:"Event"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -7424,6 +7425,9 @@ type OneOf_DatabaseUserCreate struct { type OneOf_DatabaseUserDeactivate struct { DatabaseUserDeactivate *DatabaseUserDeactivate `protobuf:"bytes,156,opt,name=DatabaseUserDeactivate,proto3,oneof" json:"DatabaseUserDeactivate,omitempty"` } +type OneOf_SpannerRPC struct { + SpannerRPC *SpannerRPC `protobuf:"bytes,158,opt,name=SpannerRPC,proto3,oneof" json:"SpannerRPC,omitempty"` +} func (*OneOf_UserLogin) isOneOf_Event() {} func (*OneOf_UserCreate) isOneOf_Event() {} @@ -7579,6 +7583,7 @@ func (*OneOf_SessionRecordingConfigUpdate) isOneOf_Event() {} func (*OneOf_ClusterNetworkingConfigUpdate) isOneOf_Event() {} func (*OneOf_DatabaseUserCreate) isOneOf_Event() {} func (*OneOf_DatabaseUserDeactivate) isOneOf_Event() {} +func (*OneOf_SpannerRPC) isOneOf_Event() {} func (m *OneOf) GetEvent() isOneOf_Event { if m != nil { @@ -8665,6 +8670,13 @@ func (m *OneOf) GetDatabaseUserDeactivate() *DatabaseUserDeactivate { return nil } +func (m *OneOf) GetSpannerRPC() *SpannerRPC { + if x, ok := m.GetEvent().(*OneOf_SpannerRPC); ok { + return x.SpannerRPC + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*OneOf) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -8822,6 +8834,7 @@ func (*OneOf) XXX_OneofWrappers() []interface{} { (*OneOf_ClusterNetworkingConfigUpdate)(nil), (*OneOf_DatabaseUserCreate)(nil), (*OneOf_DatabaseUserDeactivate)(nil), + (*OneOf_SpannerRPC)(nil), } } @@ -12422,6 +12435,60 @@ func (m *SessionRecordingConfigUpdate) XXX_DiscardUnknown() { var xxx_messageInfo_SessionRecordingConfigUpdate proto.InternalMessageInfo +// SpannerRPC is an event emitted when a Spanner client calls a Spanner RPC. +type SpannerRPC struct { + // Metadata is a common event metadata. + Metadata `protobuf:"bytes,1,opt,name=Metadata,proto3,embedded=Metadata" json:""` + // User is a common user event metadata. + UserMetadata `protobuf:"bytes,2,opt,name=User,proto3,embedded=User" json:""` + // SessionMetadata is a common event session metadata. + SessionMetadata `protobuf:"bytes,3,opt,name=Session,proto3,embedded=Session" json:""` + // Database contains database related metadata. + DatabaseMetadata `protobuf:"bytes,4,opt,name=Database,proto3,embedded=Database" json:""` + // Status indicates whether the RPC was successfully sent to the database. + Status `protobuf:"bytes,5,opt,name=Status,proto3,embedded=Status" json:""` + // Procedure is the name of the remote procedure. + Procedure string `protobuf:"bytes,6,opt,name=Procedure,proto3" json:"procedure,omitempty"` + // Args are the RPC arguments. + Args *Struct `protobuf:"bytes,7,opt,name=Args,proto3,casttype=Struct" json:"args,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *SpannerRPC) Reset() { *m = SpannerRPC{} } +func (m *SpannerRPC) String() string { return proto.CompactTextString(m) } +func (*SpannerRPC) ProtoMessage() {} +func (*SpannerRPC) Descriptor() ([]byte, []int) { + return fileDescriptor_007ba1c3d6266d56, []int{194} +} +func (m *SpannerRPC) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SpannerRPC) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SpannerRPC.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SpannerRPC) XXX_Merge(src proto.Message) { + xxx_messageInfo_SpannerRPC.Merge(m, src) +} +func (m *SpannerRPC) XXX_Size() int { + return m.Size() +} +func (m *SpannerRPC) XXX_DiscardUnknown() { + xxx_messageInfo_SpannerRPC.DiscardUnknown(m) +} + +var xxx_messageInfo_SpannerRPC proto.InternalMessageInfo + func init() { proto.RegisterEnum("events.UserKind", UserKind_name, UserKind_value) proto.RegisterEnum("events.EventAction", EventAction_name, EventAction_value) @@ -12639,6 +12706,7 @@ func init() { proto.RegisterType((*AuthPreferenceUpdate)(nil), "events.AuthPreferenceUpdate") proto.RegisterType((*ClusterNetworkingConfigUpdate)(nil), "events.ClusterNetworkingConfigUpdate") proto.RegisterType((*SessionRecordingConfigUpdate)(nil), "events.SessionRecordingConfigUpdate") + proto.RegisterType((*SpannerRPC)(nil), "events.SpannerRPC") } func init() { @@ -12646,913 +12714,918 @@ func init() { } var fileDescriptor_007ba1c3d6266d56 = []byte{ - // 14491 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x7d, 0x70, 0x24, 0xc7, - 0x75, 0x18, 0x8e, 0xfd, 0xc0, 0x62, 0xd1, 0xf8, 0x5a, 0xf4, 0x7d, 0xcd, 0x81, 0x77, 0xb7, 0xe4, - 0x50, 0x3a, 0xdd, 0x51, 0x47, 0x9c, 0x78, 0x3c, 0x92, 0x22, 0x45, 0x8a, 0x5c, 0x60, 0x81, 0xc3, - 0xf2, 0xf0, 0xb1, 0x9c, 0xc5, 0xdd, 0x89, 0x94, 0xc5, 0xf5, 0x60, 0xa7, 0x01, 0x0c, 0xb1, 0x3b, - 0xb3, 0x9a, 0x99, 0x3d, 0x1c, 0xf8, 0xfb, 0x25, 0xb1, 0x1c, 0x7f, 0xc9, 0x91, 0x15, 0x45, 0x8e, - 0xbf, 0x62, 0x57, 0xc5, 0x4e, 0x2a, 0x55, 0x8e, 0xcb, 0xb1, 0xe3, 0x38, 0x65, 0x5b, 0x76, 0x5c, - 0xb1, 0xa3, 0x7c, 0xd0, 0x51, 0x9c, 0xb2, 0x9d, 0xc4, 0x95, 0x4a, 0x1c, 0xc8, 0x71, 0xe2, 0xfc, - 0x81, 0x4a, 0xaa, 0x5c, 0x15, 0x55, 0xe2, 0x38, 0x4e, 0x2a, 0xd5, 0xaf, 0x7b, 0x66, 0xba, 0x67, - 0x66, 0x17, 0x5f, 0x27, 0x83, 0xe0, 0xe1, 0x9f, 0x3b, 0xec, 0x7b, 0xaf, 0x5f, 0xf7, 0xbc, 0x7e, - 0xdd, 0xfd, 0xba, 0xfb, 0xf5, 0x7b, 0xe8, 0xaa, 0x47, 0x9a, 0xa4, 0x6d, 0x3b, 0xde, 0xf5, 0x26, - 0x59, 0xd3, 0x1b, 0x5b, 0xd7, 0xbd, 0xad, 0x36, 0x71, 0xaf, 0x93, 0xfb, 0xc4, 0xf2, 0xfc, 0xff, - 0x26, 0xdb, 0x8e, 0xed, 0xd9, 0x38, 0xc7, 0x7e, 0x4d, 0x9c, 0x5e, 0xb3, 0xd7, 0x6c, 0x00, 0x5d, - 0xa7, 0x7f, 0x31, 0xec, 0xc4, 0x85, 0x35, 0xdb, 0x5e, 0x6b, 0x92, 0xeb, 0xf0, 0x6b, 0xa5, 0xb3, - 0x7a, 0xdd, 0xf5, 0x9c, 0x4e, 0xc3, 0xe3, 0xd8, 0x62, 0x14, 0xeb, 0x99, 0x2d, 0xe2, 0x7a, 0x7a, - 0xab, 0xcd, 0x09, 0x2e, 0x45, 0x09, 0x36, 0x1d, 0xbd, 0xdd, 0x26, 0x0e, 0xaf, 0x7c, 0xe2, 0x89, - 0xe4, 0x76, 0xc2, 0xbf, 0x9c, 0xe4, 0xe9, 0x64, 0x12, 0x9f, 0x51, 0x84, 0xa3, 0xfa, 0xe5, 0x34, - 0xca, 0x2f, 0x10, 0x4f, 0x37, 0x74, 0x4f, 0xc7, 0x17, 0x50, 0x7f, 0xc5, 0x32, 0xc8, 0x03, 0x25, - 0xf5, 0x78, 0xea, 0x4a, 0x66, 0x2a, 0xb7, 0xb3, 0x5d, 0x4c, 0x13, 0x53, 0x63, 0x40, 0x7c, 0x11, - 0x65, 0x97, 0xb7, 0xda, 0x44, 0x49, 0x3f, 0x9e, 0xba, 0x32, 0x38, 0x35, 0xb8, 0xb3, 0x5d, 0xec, - 0x07, 0x59, 0x68, 0x00, 0xc6, 0x4f, 0xa0, 0x74, 0xa5, 0xac, 0x64, 0x00, 0x39, 0xbe, 0xb3, 0x5d, - 0x1c, 0xe9, 0x98, 0xc6, 0x35, 0xbb, 0x65, 0x7a, 0xa4, 0xd5, 0xf6, 0xb6, 0xb4, 0x74, 0xa5, 0x8c, - 0x2f, 0xa3, 0xec, 0xb4, 0x6d, 0x10, 0x25, 0x0b, 0x44, 0x78, 0x67, 0xbb, 0x38, 0xda, 0xb0, 0x0d, - 0x22, 0x50, 0x01, 0x1e, 0xbf, 0x86, 0xb2, 0xcb, 0x66, 0x8b, 0x28, 0xfd, 0x8f, 0xa7, 0xae, 0x0c, - 0xdd, 0x98, 0x98, 0x64, 0x52, 0x99, 0xf4, 0xa5, 0x32, 0xb9, 0xec, 0x8b, 0x6d, 0xaa, 0xf0, 0xde, - 0x76, 0xb1, 0x6f, 0x67, 0xbb, 0x98, 0xa5, 0x92, 0xfc, 0xd2, 0xd7, 0x8b, 0x29, 0x0d, 0x4a, 0xe2, - 0x97, 0xd1, 0xd0, 0x74, 0xb3, 0xe3, 0x7a, 0xc4, 0x59, 0xd4, 0x5b, 0x44, 0xc9, 0x41, 0x85, 0x13, - 0x3b, 0xdb, 0xc5, 0xb3, 0x0d, 0x06, 0xae, 0x5b, 0x7a, 0x4b, 0xac, 0x58, 0x24, 0x57, 0x7f, 0x29, - 0x85, 0xc6, 0x6a, 0xc4, 0x75, 0x4d, 0xdb, 0x0a, 0x64, 0xf3, 0x61, 0x34, 0xc8, 0x41, 0x95, 0x32, - 0xc8, 0x67, 0x70, 0x6a, 0x60, 0x67, 0xbb, 0x98, 0x71, 0x4d, 0x43, 0x0b, 0x31, 0xf8, 0x63, 0x68, - 0xe0, 0x9e, 0xe9, 0xad, 0x2f, 0xcc, 0x96, 0xb8, 0x9c, 0xce, 0xee, 0x6c, 0x17, 0xf1, 0xa6, 0xe9, - 0xad, 0xd7, 0x5b, 0xab, 0xba, 0x50, 0xa1, 0x4f, 0x86, 0xe7, 0x51, 0xa1, 0xea, 0x98, 0xf7, 0x75, - 0x8f, 0xdc, 0x26, 0x5b, 0x55, 0xbb, 0x69, 0x36, 0xb6, 0xb8, 0x14, 0x1f, 0xdf, 0xd9, 0x2e, 0x5e, - 0x68, 0x33, 0x5c, 0x7d, 0x83, 0x6c, 0xd5, 0xdb, 0x80, 0x15, 0x98, 0xc4, 0x4a, 0xaa, 0x5f, 0xed, - 0x47, 0xc3, 0x77, 0x5c, 0xe2, 0x04, 0xed, 0xbe, 0x8c, 0xb2, 0xf4, 0x37, 0x6f, 0x32, 0xc8, 0xbc, - 0xe3, 0x12, 0x47, 0x94, 0x39, 0xc5, 0xe3, 0xab, 0xa8, 0x7f, 0xde, 0x5e, 0x33, 0x2d, 0xde, 0xec, - 0x53, 0x3b, 0xdb, 0xc5, 0xb1, 0x26, 0x05, 0x08, 0x94, 0x8c, 0x02, 0x7f, 0x12, 0x0d, 0x57, 0x5a, - 0x54, 0x87, 0x6c, 0x4b, 0xf7, 0x6c, 0x87, 0xb7, 0x16, 0xa4, 0x6b, 0x0a, 0x70, 0xa1, 0xa0, 0x44, - 0x8f, 0x5f, 0x42, 0xa8, 0x74, 0xaf, 0xa6, 0xd9, 0x4d, 0x52, 0xd2, 0x16, 0xb9, 0x32, 0x40, 0x69, - 0x7d, 0xd3, 0xad, 0x3b, 0x76, 0x93, 0xd4, 0x75, 0x47, 0xac, 0x56, 0xa0, 0xc6, 0x33, 0x68, 0xb4, - 0xd4, 0x68, 0x10, 0xd7, 0xd5, 0xc8, 0x67, 0x3b, 0xc4, 0xf5, 0x5c, 0xa5, 0xff, 0xf1, 0xcc, 0x95, - 0xc1, 0xa9, 0x8b, 0x3b, 0xdb, 0xc5, 0xf3, 0x3a, 0x60, 0xea, 0x0e, 0x47, 0x09, 0x2c, 0x22, 0x85, - 0xf0, 0x14, 0x1a, 0x29, 0xbd, 0xdb, 0x71, 0x48, 0xc5, 0x20, 0x96, 0x67, 0x7a, 0x5b, 0x5c, 0x43, - 0x2e, 0xec, 0x6c, 0x17, 0x15, 0x9d, 0x22, 0xea, 0x26, 0xc7, 0x08, 0x4c, 0xe4, 0x22, 0x78, 0x09, - 0x8d, 0xdf, 0x9a, 0xae, 0xd6, 0x88, 0x73, 0xdf, 0x6c, 0x90, 0x52, 0xa3, 0x61, 0x77, 0x2c, 0x4f, - 0x19, 0x00, 0x3e, 0x4f, 0xec, 0x6c, 0x17, 0x2f, 0xae, 0x35, 0xda, 0x75, 0x97, 0x61, 0xeb, 0x3a, - 0x43, 0x0b, 0xcc, 0xe2, 0x65, 0xf1, 0x5b, 0x68, 0x64, 0xd9, 0xa1, 0x5a, 0x68, 0x94, 0x09, 0x85, - 0x2b, 0x79, 0xd0, 0xff, 0xb3, 0x93, 0x7c, 0x02, 0x62, 0x50, 0xbf, 0x67, 0x59, 0x63, 0x3d, 0x56, - 0xa0, 0x6e, 0x00, 0x4e, 0x6c, 0xac, 0xc4, 0x0a, 0x13, 0xa4, 0xd0, 0x8f, 0x37, 0x1d, 0x62, 0xc4, - 0xb4, 0x6d, 0x10, 0xda, 0x7c, 0x75, 0x67, 0xbb, 0xf8, 0x61, 0x87, 0xd3, 0xd4, 0x7b, 0xaa, 0x5d, - 0x57, 0x56, 0x78, 0x06, 0xe5, 0xa9, 0x36, 0xdd, 0x36, 0x2d, 0x43, 0x41, 0x8f, 0xa7, 0xae, 0x8c, - 0xde, 0x28, 0xf8, 0xad, 0xf7, 0xe1, 0x53, 0xe7, 0x76, 0xb6, 0x8b, 0xa7, 0xa8, 0x0e, 0xd6, 0x37, - 0x4c, 0x4b, 0x9c, 0x22, 0x82, 0xa2, 0xea, 0xcf, 0x67, 0xd1, 0x28, 0x15, 0x8e, 0xa0, 0xc7, 0x25, - 0x3a, 0x24, 0x29, 0x84, 0x8e, 0x50, 0xb7, 0xad, 0x37, 0x08, 0x57, 0x69, 0x60, 0x67, 0xf9, 0x40, - 0x81, 0x5d, 0x94, 0x1e, 0x5f, 0x45, 0x79, 0x06, 0xaa, 0x94, 0xb9, 0x96, 0x8f, 0xec, 0x6c, 0x17, - 0x07, 0x5d, 0x80, 0xd5, 0x4d, 0x43, 0x0b, 0xd0, 0x54, 0xcd, 0xd8, 0xdf, 0x73, 0xb6, 0xeb, 0x51, - 0xe6, 0x5c, 0xc9, 0x41, 0xcd, 0x78, 0x81, 0x75, 0x8e, 0x12, 0xd5, 0x4c, 0x2e, 0x84, 0x5f, 0x44, - 0x88, 0x41, 0x4a, 0x86, 0xe1, 0x70, 0x4d, 0x3f, 0xbf, 0xb3, 0x5d, 0x3c, 0xc3, 0x59, 0xe8, 0x86, - 0x21, 0x0e, 0x13, 0x81, 0x18, 0xb7, 0xd0, 0x30, 0xfb, 0x35, 0xaf, 0xaf, 0x90, 0x26, 0x53, 0xf3, - 0xa1, 0x1b, 0x57, 0x7c, 0x69, 0xca, 0xd2, 0x99, 0x14, 0x49, 0x67, 0x2c, 0xcf, 0xd9, 0x9a, 0x2a, - 0xf2, 0x99, 0xf1, 0x1c, 0xaf, 0xaa, 0x09, 0x38, 0x71, 0x4c, 0x8a, 0x65, 0xe8, 0x84, 0x39, 0x6b, - 0x3b, 0x9b, 0xba, 0x63, 0x10, 0x63, 0x6a, 0x4b, 0x9c, 0x30, 0x57, 0x7d, 0x70, 0x7d, 0x45, 0xd4, - 0x01, 0x91, 0x1c, 0x4f, 0xa3, 0x11, 0xc6, 0xad, 0xd6, 0x59, 0x81, 0xbe, 0x1f, 0x88, 0x49, 0xcb, - 0xed, 0xac, 0x44, 0xfb, 0x5b, 0x2e, 0x33, 0xf1, 0x2a, 0x1a, 0x8f, 0x7d, 0x06, 0x2e, 0xa0, 0xcc, - 0x06, 0xd9, 0x62, 0x5d, 0xad, 0xd1, 0x3f, 0xf1, 0x69, 0xd4, 0x7f, 0x5f, 0x6f, 0x76, 0xf8, 0x3a, - 0xa4, 0xb1, 0x1f, 0x2f, 0xa5, 0x3f, 0x9e, 0xa2, 0xd3, 0x36, 0x9e, 0xb6, 0x2d, 0x8b, 0x34, 0x3c, - 0x71, 0xe6, 0x7e, 0x1e, 0x0d, 0xce, 0xdb, 0x0d, 0xbd, 0x09, 0x7d, 0xc0, 0x74, 0x46, 0xd9, 0xd9, - 0x2e, 0x9e, 0xa6, 0xc2, 0x9f, 0x6c, 0x52, 0x8c, 0xd0, 0xa6, 0x90, 0x94, 0x76, 0x9e, 0x46, 0x5a, - 0xb6, 0x47, 0xa0, 0x60, 0x3a, 0xec, 0x3c, 0x28, 0xe8, 0x00, 0x4a, 0xec, 0xbc, 0x90, 0x18, 0x5f, - 0x47, 0xf9, 0x2a, 0x5d, 0xac, 0x1a, 0x76, 0x93, 0x2b, 0x0e, 0xcc, 0xa7, 0xb0, 0x80, 0x89, 0x0a, - 0xef, 0x13, 0xa9, 0x73, 0x68, 0x74, 0xba, 0x69, 0x12, 0xcb, 0x13, 0x5b, 0x4d, 0x87, 0x43, 0x69, - 0x8d, 0x58, 0x9e, 0xd8, 0x6a, 0x18, 0x38, 0x3a, 0x85, 0x8a, 0xad, 0x0e, 0x48, 0xd5, 0x7f, 0x99, - 0x41, 0xe7, 0x6f, 0x77, 0x56, 0x88, 0x63, 0x11, 0x8f, 0xb8, 0x7c, 0x55, 0x0b, 0xb8, 0x2e, 0xa2, - 0xf1, 0x18, 0x92, 0x73, 0x87, 0xd5, 0x66, 0x23, 0x40, 0xd6, 0xf9, 0x42, 0x29, 0x4e, 0x59, 0xb1, - 0xa2, 0x78, 0x0e, 0x8d, 0x85, 0x40, 0xda, 0x08, 0x57, 0x49, 0xc3, 0x7c, 0x7c, 0x69, 0x67, 0xbb, - 0x38, 0x21, 0x70, 0xa3, 0xcd, 0x16, 0xb5, 0x2f, 0x5a, 0x0c, 0xdf, 0x46, 0x85, 0x10, 0x74, 0xcb, - 0xb1, 0x3b, 0x6d, 0x57, 0xc9, 0x00, 0xab, 0xe2, 0xce, 0x76, 0xf1, 0x31, 0x81, 0xd5, 0x1a, 0x20, - 0xc5, 0x55, 0x30, 0x5a, 0x10, 0x7f, 0x47, 0x4a, 0xe4, 0xc6, 0x47, 0x50, 0x16, 0x46, 0xd0, 0x0b, - 0xfe, 0x08, 0xea, 0x2a, 0xa4, 0xc9, 0x68, 0x49, 0x3e, 0xa0, 0x22, 0xcd, 0x88, 0x0d, 0xa8, 0x58, - 0x8d, 0x13, 0xd3, 0xe8, 0x4c, 0x22, 0xaf, 0x7d, 0x69, 0xf5, 0x1f, 0x66, 0x44, 0x2e, 0x55, 0xdb, - 0x08, 0x3a, 0x73, 0x49, 0xec, 0xcc, 0xaa, 0x6d, 0x80, 0xa9, 0x93, 0x0a, 0x17, 0x20, 0xa1, 0xb1, - 0x6d, 0xdb, 0x88, 0x5a, 0x3c, 0xf1, 0xb2, 0xf8, 0x6d, 0x74, 0x36, 0x06, 0x64, 0x53, 0x2d, 0xd3, - 0xfe, 0xcb, 0x3b, 0xdb, 0x45, 0x35, 0x81, 0x6b, 0x74, 0xe6, 0xed, 0xc2, 0x05, 0xeb, 0xe8, 0x9c, - 0x20, 0x75, 0xdb, 0xf2, 0x74, 0xd3, 0xe2, 0x16, 0x1a, 0x1b, 0x25, 0x1f, 0xd9, 0xd9, 0x2e, 0x3e, - 0x29, 0xea, 0xa0, 0x4f, 0x13, 0x6d, 0x7c, 0x37, 0x3e, 0xd8, 0x40, 0x4a, 0x02, 0xaa, 0xd2, 0xd2, - 0xd7, 0x7c, 0xb3, 0xf3, 0xca, 0xce, 0x76, 0xf1, 0x43, 0x89, 0x75, 0x98, 0x94, 0x4a, 0x5c, 0xe6, - 0xba, 0x71, 0xc2, 0x1a, 0xc2, 0x21, 0x6e, 0xd1, 0x36, 0x08, 0x7c, 0x43, 0x3f, 0xf0, 0x57, 0x77, - 0xb6, 0x8b, 0x97, 0x04, 0xfe, 0x96, 0x6d, 0x90, 0x68, 0xf3, 0x13, 0x4a, 0xab, 0xbf, 0x94, 0x41, - 0x97, 0x6a, 0xa5, 0x85, 0xf9, 0x8a, 0xe1, 0xdb, 0x05, 0x55, 0xc7, 0xbe, 0x6f, 0x1a, 0xc2, 0xe8, - 0x5d, 0x41, 0xe7, 0x22, 0xa8, 0x19, 0x30, 0x45, 0x02, 0x8b, 0x14, 0xbe, 0xcd, 0xb7, 0x39, 0xda, - 0x9c, 0xa6, 0xce, 0xec, 0x95, 0xba, 0x64, 0x8e, 0x77, 0x63, 0x44, 0xfb, 0x28, 0x82, 0xaa, 0xad, - 0xdb, 0x8e, 0xd7, 0xe8, 0x78, 0x5c, 0x09, 0xa0, 0x8f, 0x62, 0x75, 0xb8, 0x9c, 0xa8, 0x47, 0x15, - 0x3e, 0x1f, 0xfc, 0xf9, 0x14, 0x2a, 0x94, 0x3c, 0xcf, 0x31, 0x57, 0x3a, 0x1e, 0x59, 0xd0, 0xdb, - 0x6d, 0xd3, 0x5a, 0x83, 0xb1, 0x3e, 0x74, 0xe3, 0xe5, 0x60, 0x7d, 0xeb, 0x29, 0x89, 0xc9, 0x68, - 0x71, 0x61, 0x88, 0xea, 0x3e, 0xaa, 0xde, 0x62, 0x38, 0x71, 0x88, 0x46, 0xcb, 0xd1, 0x21, 0x9a, - 0xc8, 0x6b, 0x5f, 0x43, 0xf4, 0xcb, 0x19, 0x74, 0x61, 0x69, 0xc3, 0xd3, 0x35, 0xe2, 0xda, 0x1d, - 0xa7, 0x41, 0xdc, 0x3b, 0x6d, 0x43, 0xf7, 0x48, 0x38, 0x52, 0x8b, 0xa8, 0xbf, 0x64, 0x18, 0xc4, - 0x00, 0x76, 0xfd, 0x6c, 0xef, 0xa4, 0x53, 0x80, 0xc6, 0xe0, 0xf8, 0xc3, 0x68, 0x80, 0x97, 0x01, - 0xee, 0xfd, 0x53, 0x43, 0x3b, 0xdb, 0xc5, 0x81, 0x0e, 0x03, 0x69, 0x3e, 0x8e, 0x92, 0x95, 0x49, - 0x93, 0x50, 0xb2, 0x4c, 0x48, 0x66, 0x30, 0x90, 0xe6, 0xe3, 0xf0, 0x1b, 0x68, 0x14, 0xd8, 0x06, - 0xed, 0xe1, 0x73, 0xdf, 0x69, 0x5f, 0xba, 0x62, 0x63, 0xd9, 0xd2, 0x04, 0xad, 0xa9, 0x3b, 0x7e, - 0x01, 0x2d, 0xc2, 0x00, 0xdf, 0x43, 0x05, 0xde, 0x88, 0x90, 0x69, 0x7f, 0x0f, 0xa6, 0x67, 0x76, - 0xb6, 0x8b, 0xe3, 0xbc, 0xfd, 0x02, 0xdb, 0x18, 0x13, 0xca, 0x98, 0x37, 0x3b, 0x64, 0x9c, 0xdb, - 0x8d, 0x31, 0xff, 0x62, 0x91, 0x71, 0x94, 0x89, 0xfa, 0x26, 0x1a, 0x16, 0x0b, 0xe2, 0xb3, 0xb0, - 0x3f, 0x65, 0xe3, 0x04, 0x76, 0xb6, 0xa6, 0x01, 0x9b, 0xd2, 0x67, 0xd0, 0x50, 0x99, 0xb8, 0x0d, - 0xc7, 0x6c, 0x53, 0xab, 0x81, 0x2b, 0xf9, 0xd8, 0xce, 0x76, 0x71, 0xc8, 0x08, 0xc1, 0x9a, 0x48, - 0xa3, 0xfe, 0x8f, 0x14, 0x3a, 0x4b, 0x79, 0x97, 0x5c, 0xd7, 0x5c, 0xb3, 0x5a, 0xe2, 0xb2, 0x7d, - 0x0d, 0xe5, 0x6a, 0x50, 0x1f, 0xaf, 0xe9, 0xf4, 0xce, 0x76, 0xb1, 0xc0, 0x5a, 0x20, 0xe8, 0x21, - 0xa7, 0x09, 0x36, 0x67, 0xe9, 0x5d, 0x36, 0x67, 0xd4, 0x1c, 0xf5, 0x74, 0xc7, 0x33, 0xad, 0xb5, - 0x9a, 0xa7, 0x7b, 0x1d, 0x57, 0x32, 0x47, 0x39, 0xa6, 0xee, 0x02, 0x4a, 0x32, 0x47, 0xa5, 0x42, - 0xf8, 0x55, 0x34, 0x3c, 0x63, 0x19, 0x21, 0x13, 0x36, 0x21, 0x3e, 0x46, 0xad, 0x44, 0x02, 0xf0, - 0x38, 0x0b, 0xa9, 0x80, 0xfa, 0x77, 0x52, 0x48, 0x61, 0x3b, 0xa9, 0x79, 0xd3, 0xf5, 0x16, 0x48, - 0x6b, 0x45, 0x98, 0x9d, 0x66, 0xfd, 0xad, 0x19, 0xc5, 0x09, 0x6b, 0x11, 0x98, 0x02, 0x7c, 0x6b, - 0xd6, 0x34, 0x5d, 0x2f, 0x3a, 0x19, 0x46, 0x4a, 0xe1, 0x0a, 0x1a, 0x60, 0x9c, 0x99, 0x2d, 0x31, - 0x74, 0x43, 0xf1, 0x15, 0x21, 0x5a, 0x35, 0x53, 0x86, 0x16, 0x23, 0x16, 0xf7, 0xd6, 0xbc, 0xbc, - 0xfa, 0x77, 0xd3, 0xa8, 0x10, 0x2d, 0x84, 0xef, 0xa1, 0xfc, 0xeb, 0xb6, 0x69, 0x11, 0x63, 0xc9, - 0x82, 0x16, 0xf6, 0x3e, 0x61, 0xf0, 0xed, 0xe8, 0x53, 0xef, 0x40, 0x99, 0xba, 0x2d, 0xec, 0x4c, - 0xe1, 0xc0, 0x21, 0x60, 0x86, 0xdf, 0x42, 0x83, 0xd4, 0x06, 0xbc, 0x0f, 0x9c, 0xd3, 0xbb, 0x72, - 0x7e, 0x9c, 0x73, 0x3e, 0xed, 0xb0, 0x42, 0x71, 0xd6, 0x21, 0x3b, 0xaa, 0x57, 0x1a, 0xd1, 0x5d, - 0xdb, 0xe2, 0x3d, 0x0f, 0x7a, 0xe5, 0x00, 0x44, 0xd4, 0x2b, 0x46, 0x43, 0x4d, 0x57, 0xf6, 0xb1, - 0xd0, 0x0d, 0xc2, 0xbe, 0x83, 0xc9, 0x2a, 0xda, 0x03, 0x02, 0xb1, 0xfa, 0x5d, 0x69, 0xf4, 0x74, - 0x28, 0x32, 0x8d, 0xdc, 0x37, 0xc9, 0x26, 0x17, 0xe7, 0xba, 0xd9, 0xe6, 0x1b, 0x3f, 0xaa, 0xf2, - 0xee, 0xf4, 0xba, 0x6e, 0xad, 0x11, 0x03, 0x5f, 0x45, 0xfd, 0x74, 0x77, 0xee, 0x2a, 0x29, 0x30, - 0xd7, 0x60, 0x3a, 0xa1, 0xbb, 0x78, 0xb1, 0x47, 0x18, 0x05, 0xb6, 0x51, 0x6e, 0xd9, 0xd1, 0x4d, - 0xcf, 0xef, 0xd9, 0x52, 0xbc, 0x67, 0xf7, 0x50, 0xe3, 0x24, 0xe3, 0xc1, 0xe6, 0x7c, 0x10, 0x84, - 0x07, 0x00, 0x51, 0x10, 0x8c, 0x64, 0xe2, 0x45, 0x34, 0x24, 0x10, 0xef, 0x6b, 0x52, 0xff, 0x4a, - 0x56, 0xd4, 0x75, 0xbf, 0x59, 0x5c, 0xd7, 0xaf, 0x53, 0x1d, 0x75, 0x5d, 0x6a, 0x55, 0x30, 0x25, - 0xe7, 0x9a, 0x08, 0x20, 0x59, 0x13, 0x01, 0x84, 0x9f, 0x45, 0x79, 0xc6, 0x22, 0xd8, 0x7b, 0xc2, - 0xbe, 0xd5, 0x01, 0x98, 0xbc, 0x34, 0x07, 0x84, 0xf8, 0xa7, 0x52, 0xe8, 0x62, 0x4f, 0x49, 0x80, - 0x32, 0x0c, 0xdd, 0x78, 0xee, 0x40, 0x62, 0x9c, 0x7a, 0x7a, 0x67, 0xbb, 0x78, 0xb5, 0x15, 0x90, - 0xd4, 0x1d, 0x81, 0xa6, 0xde, 0x60, 0x44, 0x42, 0xbb, 0x7a, 0x37, 0x85, 0x1a, 0x8f, 0xac, 0xd2, - 0x59, 0x38, 0x7f, 0xb1, 0x1a, 0x5b, 0x7e, 0x23, 0xb3, 0xa1, 0xf1, 0xc8, 0xbf, 0x77, 0xd5, 0x27, - 0x49, 0xa8, 0xa6, 0x0b, 0x17, 0xdc, 0x40, 0xe7, 0x18, 0xa6, 0xac, 0x6f, 0x2d, 0xad, 0x2e, 0xd8, - 0x96, 0xb7, 0xee, 0x57, 0xd0, 0x2f, 0x1e, 0x60, 0x40, 0x05, 0x86, 0xbe, 0x55, 0xb7, 0x57, 0xeb, - 0x2d, 0x4a, 0x95, 0x50, 0x47, 0x37, 0x4e, 0x74, 0xa2, 0xe5, 0x63, 0xce, 0x9f, 0x82, 0x72, 0xe1, - 0xf1, 0x92, 0x3f, 0x4e, 0xe3, 0x13, 0x4e, 0xa4, 0x90, 0x5a, 0x41, 0xc3, 0xf3, 0x76, 0x63, 0x23, - 0x50, 0x97, 0x17, 0x51, 0x6e, 0x59, 0x77, 0xd6, 0x88, 0x07, 0xb2, 0x18, 0xba, 0x31, 0x3e, 0xc9, - 0x8e, 0x6c, 0x29, 0x11, 0x43, 0x4c, 0x8d, 0xf2, 0xd9, 0x20, 0xe7, 0xc1, 0x6f, 0x8d, 0x17, 0x50, - 0xbf, 0xde, 0x8f, 0x86, 0xf9, 0xf1, 0x22, 0xcc, 0xe6, 0xf8, 0xa5, 0xf0, 0xc0, 0x96, 0x4f, 0x5f, - 0xc1, 0x11, 0x4b, 0x70, 0x34, 0x34, 0x4c, 0x99, 0xfd, 0xd6, 0x76, 0x31, 0xb5, 0xb3, 0x5d, 0xec, - 0xd3, 0xf2, 0xc2, 0xa6, 0x32, 0x5c, 0x6f, 0x84, 0x05, 0x56, 0x3c, 0x30, 0x8c, 0x94, 0x65, 0xeb, - 0xcf, 0xab, 0x68, 0x80, 0xb7, 0x81, 0x6b, 0xdc, 0xb9, 0xf0, 0x1c, 0x42, 0x3a, 0x26, 0x8d, 0x94, - 0xf6, 0x4b, 0xe1, 0x97, 0x51, 0x8e, 0xed, 0xed, 0xb9, 0x00, 0xce, 0x26, 0x9f, 0x63, 0x44, 0x8a, - 0xf3, 0x32, 0x78, 0x0e, 0xa1, 0x70, 0x5f, 0x1f, 0x9c, 0x0a, 0x73, 0x0e, 0xf1, 0x1d, 0x7f, 0x84, - 0x8b, 0x50, 0x16, 0x3f, 0x8f, 0x86, 0x97, 0x89, 0xd3, 0x32, 0x2d, 0xbd, 0x59, 0x33, 0xdf, 0xf5, - 0x0f, 0x86, 0x61, 0xe1, 0x75, 0xcd, 0x77, 0xc5, 0x91, 0x2b, 0xd1, 0xe1, 0xcf, 0x24, 0xed, 0x9b, - 0x07, 0xa0, 0x21, 0x4f, 0xec, 0xba, 0xa1, 0x8c, 0xb4, 0x27, 0x61, 0x1b, 0xfd, 0x06, 0x1a, 0x91, - 0xb6, 0x4c, 0xfc, 0xe4, 0xef, 0x62, 0x9c, 0xb5, 0xb0, 0xff, 0x8b, 0xb0, 0x95, 0x39, 0x50, 0x4d, - 0xae, 0x58, 0xa6, 0x67, 0xea, 0xcd, 0x69, 0xbb, 0xd5, 0xd2, 0x2d, 0x43, 0x19, 0x0c, 0x35, 0xd9, - 0x64, 0x98, 0x7a, 0x83, 0xa1, 0x44, 0x4d, 0x96, 0x0b, 0xd1, 0x6d, 0x39, 0xef, 0x43, 0x8d, 0x34, - 0x6c, 0x87, 0xda, 0x02, 0x70, 0xb0, 0xc7, 0xb7, 0xe5, 0x2e, 0xc3, 0xd5, 0x1d, 0x1f, 0x29, 0x1a, - 0xdb, 0xd1, 0x82, 0xaf, 0x67, 0xf3, 0x43, 0x85, 0xe1, 0xe8, 0x59, 0xac, 0xfa, 0xb7, 0x33, 0x68, - 0x88, 0x93, 0xd2, 0xa5, 0xf4, 0x44, 0xc1, 0x0f, 0xa3, 0xe0, 0x89, 0x8a, 0x9a, 0x7b, 0x58, 0x8a, - 0xaa, 0x7e, 0x21, 0x1d, 0xcc, 0x46, 0x55, 0xc7, 0xb4, 0x0e, 0x37, 0x1b, 0x5d, 0x46, 0x68, 0x7a, - 0xbd, 0x63, 0x6d, 0xb0, 0x3b, 0xa7, 0x74, 0x78, 0xe7, 0xd4, 0x30, 0x35, 0x01, 0x83, 0x2f, 0xa2, - 0x6c, 0x99, 0xf2, 0xa7, 0x3d, 0x33, 0x3c, 0x35, 0xf8, 0x1e, 0xe3, 0x94, 0x7a, 0x5a, 0x03, 0x30, - 0xdd, 0x5c, 0x4d, 0x6d, 0x79, 0x84, 0x99, 0xb3, 0x19, 0xb6, 0xb9, 0x5a, 0xa1, 0x00, 0x8d, 0xc1, - 0xf1, 0x4d, 0x34, 0x5e, 0x26, 0x4d, 0x7d, 0x6b, 0xc1, 0x6c, 0x36, 0x4d, 0x97, 0x34, 0x6c, 0xcb, - 0x70, 0x41, 0xc8, 0xbc, 0xba, 0x96, 0xab, 0xc5, 0x09, 0xb0, 0x8a, 0x72, 0x4b, 0xab, 0xab, 0x2e, - 0xf1, 0x40, 0x7c, 0x99, 0x29, 0x44, 0x27, 0x67, 0x1b, 0x20, 0x1a, 0xc7, 0xa8, 0x3f, 0x9b, 0xa2, - 0xbb, 0x17, 0x77, 0xc3, 0xb3, 0xdb, 0x81, 0x96, 0x1f, 0x4a, 0x24, 0x57, 0x43, 0xbb, 0x22, 0x0d, - 0x5f, 0x3b, 0xc6, 0xbf, 0x76, 0x80, 0xdb, 0x16, 0xa1, 0x45, 0x91, 0xf8, 0x55, 0x99, 0x5d, 0xbe, - 0x4a, 0xfd, 0xa3, 0x34, 0x3a, 0xc7, 0x5b, 0x3c, 0xdd, 0x34, 0xdb, 0x2b, 0xb6, 0xee, 0x18, 0x1a, - 0x69, 0x10, 0xf3, 0x3e, 0x39, 0x9e, 0x03, 0x4f, 0x1e, 0x3a, 0xd9, 0x43, 0x0c, 0x9d, 0x1b, 0xb0, - 0x11, 0xa4, 0x92, 0x81, 0x03, 0x5f, 0x66, 0x54, 0x14, 0x76, 0xb6, 0x8b, 0xc3, 0x06, 0x03, 0xc3, - 0x71, 0xbd, 0x26, 0x12, 0x51, 0x25, 0x99, 0x27, 0xd6, 0x9a, 0xb7, 0x0e, 0x4a, 0xd2, 0xcf, 0x94, - 0xa4, 0x09, 0x10, 0x8d, 0x63, 0xd4, 0xff, 0x96, 0x46, 0xa7, 0xa3, 0x22, 0xaf, 0x11, 0xcb, 0x38, - 0x91, 0xf7, 0x37, 0x47, 0xde, 0xdf, 0xc8, 0xa0, 0xc7, 0x78, 0x99, 0xda, 0xba, 0xee, 0x10, 0xa3, - 0x6c, 0x3a, 0xa4, 0xe1, 0xd9, 0xce, 0xd6, 0x31, 0x36, 0xa0, 0x1e, 0x9e, 0xd8, 0x6f, 0xa2, 0x1c, - 0xdf, 0xfe, 0xb3, 0x75, 0x66, 0x34, 0x68, 0x09, 0x40, 0x63, 0x2b, 0x14, 0x3b, 0x3a, 0x88, 0x74, - 0x56, 0x6e, 0x2f, 0x9d, 0xf5, 0x71, 0x34, 0x12, 0x88, 0x1e, 0x36, 0xa2, 0x03, 0xa1, 0xb5, 0x65, - 0xf8, 0x08, 0xd8, 0x8b, 0x6a, 0x32, 0x21, 0xd4, 0xe6, 0x03, 0x2a, 0x65, 0xb0, 0x86, 0x46, 0x78, - 0x6d, 0x41, 0x39, 0xd3, 0xd0, 0x44, 0x22, 0x75, 0x3b, 0x8b, 0x26, 0x92, 0xbb, 0x5d, 0x23, 0xba, - 0x71, 0xd2, 0xeb, 0x1f, 0xc8, 0x5e, 0xc7, 0x4f, 0xa0, 0x6c, 0x55, 0xf7, 0xd6, 0xf9, 0x1d, 0x36, - 0xdc, 0xe7, 0xae, 0x9a, 0x4d, 0x52, 0x6f, 0xeb, 0xde, 0xba, 0x06, 0x28, 0x61, 0xce, 0x40, 0xc0, - 0x31, 0x61, 0xce, 0x10, 0x16, 0xfb, 0xa1, 0xc7, 0x53, 0x57, 0xb2, 0x89, 0x8b, 0xfd, 0xd7, 0xb3, - 0xdd, 0xe6, 0x95, 0x7b, 0x8e, 0xe9, 0x91, 0x13, 0x0d, 0x3b, 0xd1, 0xb0, 0x43, 0x6a, 0xd8, 0xef, - 0xa4, 0xd1, 0x48, 0xb0, 0x69, 0x7a, 0x87, 0x34, 0x8e, 0x66, 0xad, 0x0a, 0xb7, 0x32, 0x99, 0x43, - 0x6f, 0x65, 0x0e, 0xa3, 0x50, 0x6a, 0x70, 0xe4, 0xc9, 0x4c, 0x03, 0x90, 0x18, 0x3b, 0xf2, 0x0c, - 0x0e, 0x3a, 0x9f, 0x40, 0x03, 0x0b, 0xfa, 0x03, 0xb3, 0xd5, 0x69, 0x71, 0x2b, 0x1d, 0x7c, 0xb2, - 0x5a, 0xfa, 0x03, 0xcd, 0x87, 0xab, 0xff, 0x3a, 0x85, 0x46, 0xb9, 0x50, 0x39, 0xf3, 0x43, 0x49, - 0x35, 0x94, 0x4e, 0xfa, 0xd0, 0xd2, 0xc9, 0x1c, 0x5c, 0x3a, 0xea, 0x8f, 0x65, 0x90, 0x32, 0x6b, - 0x36, 0xc9, 0xb2, 0xa3, 0x5b, 0xee, 0x2a, 0x71, 0xf8, 0x76, 0x7a, 0x86, 0xb2, 0x3a, 0xd4, 0x07, - 0x0a, 0x53, 0x4a, 0xfa, 0x40, 0x53, 0xca, 0x47, 0xd1, 0x20, 0x6f, 0x4c, 0xe0, 0x0f, 0x08, 0xa3, - 0xc6, 0xf1, 0x81, 0x5a, 0x88, 0xa7, 0xc4, 0xa5, 0x76, 0xdb, 0xb1, 0xef, 0x13, 0x87, 0xdd, 0x52, - 0x71, 0x62, 0xdd, 0x07, 0x6a, 0x21, 0x5e, 0xe0, 0x4c, 0x7c, 0x7b, 0x51, 0xe4, 0x4c, 0x1c, 0x2d, - 0xc4, 0xe3, 0x2b, 0x28, 0x3f, 0x6f, 0x37, 0x74, 0x10, 0x34, 0x9b, 0x56, 0x86, 0x77, 0xb6, 0x8b, - 0xf9, 0x26, 0x87, 0x69, 0x01, 0x96, 0x52, 0x96, 0xed, 0x4d, 0xab, 0x69, 0xeb, 0xcc, 0x71, 0x25, - 0xcf, 0x28, 0x0d, 0x0e, 0xd3, 0x02, 0x2c, 0xa5, 0xa4, 0x32, 0x07, 0x87, 0xa0, 0x7c, 0xc8, 0x73, - 0x95, 0xc3, 0xb4, 0x00, 0xab, 0xfe, 0x6c, 0x96, 0x6a, 0xaf, 0x6b, 0xbe, 0xfb, 0xc8, 0xaf, 0x0b, - 0xe1, 0x80, 0xe9, 0x3f, 0xc0, 0x80, 0x79, 0x64, 0x0e, 0xec, 0xd4, 0xff, 0x39, 0x80, 0x10, 0x97, - 0xfe, 0xcc, 0xc9, 0xe6, 0xf0, 0x70, 0x5a, 0x53, 0x46, 0xe3, 0x33, 0xd6, 0xba, 0x6e, 0x35, 0x88, - 0x11, 0x1e, 0x5b, 0xe6, 0x60, 0x68, 0x83, 0x3f, 0x2e, 0xe1, 0xc8, 0xf0, 0xdc, 0x52, 0x8b, 0x17, - 0xc0, 0xcf, 0xa0, 0xa1, 0x8a, 0xe5, 0x11, 0x47, 0x6f, 0x78, 0xe6, 0x7d, 0xc2, 0xa7, 0x06, 0xb8, - 0x19, 0x36, 0x43, 0xb0, 0x26, 0xd2, 0xe0, 0x9b, 0x68, 0xb8, 0xaa, 0x3b, 0x9e, 0xd9, 0x30, 0xdb, - 0xba, 0xe5, 0xb9, 0x4a, 0x1e, 0x66, 0x34, 0xb0, 0x30, 0xda, 0x02, 0x5c, 0x93, 0xa8, 0xf0, 0x67, - 0xd0, 0x20, 0x6c, 0x4d, 0xc1, 0xe9, 0x79, 0x70, 0xd7, 0x8b, 0xc3, 0x27, 0x43, 0xd7, 0x3e, 0x76, - 0xfa, 0x0a, 0x37, 0xc0, 0xd1, 0xbb, 0xc3, 0x80, 0x23, 0xfe, 0x14, 0x1a, 0x98, 0xb1, 0x0c, 0x60, - 0x8e, 0x76, 0x65, 0xae, 0x72, 0xe6, 0x67, 0x43, 0xe6, 0x76, 0x3b, 0xc2, 0xdb, 0x67, 0x97, 0x3c, - 0xca, 0x86, 0xbe, 0x79, 0xa3, 0x6c, 0xf8, 0x9b, 0x70, 0x2c, 0x3e, 0xf2, 0xb0, 0x8e, 0xc5, 0x47, - 0x0f, 0x78, 0x2c, 0xae, 0xbe, 0x8b, 0x86, 0xa6, 0xaa, 0xb3, 0xc1, 0xe8, 0x3d, 0x8f, 0x32, 0x55, - 0xee, 0xa9, 0x90, 0x65, 0xf6, 0x4c, 0xdb, 0x34, 0x34, 0x0a, 0xc3, 0x57, 0x51, 0x7e, 0x1a, 0xdc, - 0xdf, 0xf8, 0x2d, 0x62, 0x96, 0xad, 0x7f, 0x0d, 0x80, 0x81, 0x07, 0xab, 0x8f, 0xc6, 0x1f, 0x46, - 0x03, 0x55, 0xc7, 0x5e, 0x73, 0xf4, 0x16, 0x5f, 0x83, 0xc1, 0x55, 0xa4, 0xcd, 0x40, 0x9a, 0x8f, - 0x53, 0xbf, 0x3f, 0xe5, 0x9b, 0xed, 0xb4, 0x44, 0xad, 0x03, 0x47, 0xf3, 0x50, 0x77, 0x9e, 0x95, - 0x70, 0x19, 0x48, 0xf3, 0x71, 0xf8, 0x2a, 0xea, 0x9f, 0x71, 0x1c, 0xdb, 0x11, 0x1d, 0xc5, 0x09, - 0x05, 0x88, 0xd7, 0xbd, 0x40, 0x81, 0x5f, 0x40, 0x43, 0x6c, 0xce, 0x61, 0x27, 0x9a, 0x99, 0x5e, - 0x37, 0xa5, 0x22, 0xa5, 0xfa, 0xd5, 0x8c, 0x60, 0xb3, 0x31, 0x89, 0x3f, 0x82, 0xb7, 0x02, 0xcf, - 0xa2, 0xcc, 0x54, 0x75, 0x96, 0x4f, 0x80, 0xa7, 0xfc, 0xa2, 0x82, 0xaa, 0x44, 0xca, 0x51, 0x6a, - 0x7c, 0x01, 0x65, 0xab, 0x54, 0x7d, 0x72, 0xa0, 0x1e, 0xf9, 0x9d, 0xed, 0x62, 0xb6, 0x4d, 0xf5, - 0x07, 0xa0, 0x80, 0xa5, 0x9b, 0x19, 0xb6, 0x63, 0x62, 0xd8, 0x70, 0x1f, 0x73, 0x01, 0x65, 0x4b, - 0xce, 0xda, 0x7d, 0x3e, 0x6b, 0x01, 0x56, 0x77, 0xd6, 0xee, 0x6b, 0x00, 0xc5, 0xd7, 0x11, 0xd2, - 0x88, 0xd7, 0x71, 0x2c, 0x78, 0xc3, 0x31, 0x08, 0xe7, 0x6f, 0x30, 0x1b, 0x3a, 0x00, 0xad, 0x37, - 0x6c, 0x83, 0x68, 0x02, 0x89, 0xfa, 0xb7, 0xc2, 0x8b, 0x9d, 0xb2, 0xe9, 0x6e, 0x9c, 0x74, 0xe1, - 0x3e, 0xba, 0x50, 0xe7, 0x47, 0x9c, 0xf1, 0x4e, 0x2a, 0xa2, 0xfe, 0xd9, 0xa6, 0xbe, 0xe6, 0x42, - 0x1f, 0x72, 0x5f, 0xb2, 0x55, 0x0a, 0xd0, 0x18, 0x3c, 0xd2, 0x4f, 0xf9, 0xdd, 0xfb, 0xe9, 0x87, - 0xfa, 0x83, 0xd1, 0xb6, 0x48, 0xbc, 0x4d, 0xdb, 0x39, 0xe9, 0xaa, 0xbd, 0x76, 0xd5, 0x65, 0x34, - 0x50, 0x73, 0x1a, 0xc2, 0xd1, 0x05, 0xec, 0x07, 0x5c, 0xa7, 0xc1, 0x8e, 0x2d, 0x7c, 0x24, 0xa5, - 0x2b, 0xbb, 0x1e, 0xd0, 0x0d, 0x84, 0x74, 0x86, 0xeb, 0x71, 0x3a, 0x8e, 0xe4, 0x74, 0x55, 0xdb, - 0xf1, 0x78, 0xc7, 0x05, 0x74, 0x6d, 0xdb, 0xf1, 0x34, 0x1f, 0x89, 0x3f, 0x8a, 0xd0, 0xf2, 0x74, - 0xf5, 0x2e, 0x71, 0x40, 0x5c, 0x83, 0xa1, 0x2f, 0xe0, 0x7d, 0x06, 0xd2, 0x04, 0x34, 0x5e, 0x46, - 0x83, 0x4b, 0x6d, 0xe2, 0xb0, 0xad, 0x10, 0x7b, 0x95, 0xf1, 0x91, 0x88, 0x68, 0x79, 0xbf, 0x4f, - 0xf2, 0xff, 0x03, 0x72, 0xb6, 0xbe, 0xd8, 0xfe, 0x4f, 0x2d, 0x64, 0x84, 0x5f, 0x40, 0xb9, 0x12, - 0xb3, 0xf3, 0x86, 0x80, 0x65, 0x20, 0x32, 0xd8, 0x82, 0x32, 0x14, 0xdb, 0xb3, 0xeb, 0xf0, 0xb7, - 0xc6, 0xc9, 0xd5, 0xab, 0xa8, 0x10, 0xad, 0x06, 0x0f, 0xa1, 0x81, 0xe9, 0xa5, 0xc5, 0xc5, 0x99, - 0xe9, 0xe5, 0x42, 0x1f, 0xce, 0xa3, 0x6c, 0x6d, 0x66, 0xb1, 0x5c, 0x48, 0xa9, 0x3f, 0x2d, 0xcc, - 0x20, 0x54, 0xb5, 0x4e, 0xae, 0x86, 0x0f, 0x75, 0xdf, 0x52, 0x80, 0xfb, 0x50, 0x38, 0x31, 0x68, - 0x99, 0x9e, 0x47, 0x0c, 0xbe, 0x4a, 0xc0, 0x7d, 0xa1, 0xf7, 0x40, 0x8b, 0xe1, 0xf1, 0x35, 0x34, - 0x02, 0x30, 0x7e, 0x45, 0xc8, 0xf6, 0xc7, 0xbc, 0x80, 0xf3, 0x40, 0x93, 0x91, 0xea, 0xd7, 0xc2, - 0xdb, 0xe1, 0x79, 0xa2, 0x1f, 0xd7, 0x1b, 0xc5, 0xf7, 0x49, 0x7f, 0xa9, 0x7f, 0x9a, 0x65, 0x4f, - 0x40, 0xd8, 0xa3, 0xbb, 0xa3, 0x10, 0x65, 0x78, 0xa4, 0x9b, 0xd9, 0xc7, 0x91, 0xee, 0x35, 0x94, - 0x5b, 0x20, 0xde, 0xba, 0xed, 0x3b, 0x7e, 0x81, 0x87, 0x5e, 0x0b, 0x20, 0xa2, 0x87, 0x1e, 0xa3, - 0xc1, 0x1b, 0x08, 0xfb, 0x2f, 0xea, 0x02, 0x47, 0x6c, 0xff, 0x08, 0xf9, 0x5c, 0x6c, 0x9f, 0x52, - 0x83, 0xe7, 0xb4, 0xe0, 0x63, 0x7f, 0x3a, 0x70, 0xf4, 0x16, 0x3c, 0xb1, 0xfe, 0x64, 0xbb, 0x98, - 0x63, 0x34, 0x5a, 0x02, 0x5b, 0xfc, 0x06, 0x1a, 0x5c, 0x98, 0x2d, 0xf1, 0xd7, 0x75, 0xcc, 0x2b, - 0xe2, 0x7c, 0x20, 0x45, 0x1f, 0x11, 0x88, 0x04, 0xde, 0xdb, 0xb4, 0x56, 0xf5, 0xf8, 0xe3, 0xba, - 0x90, 0x0b, 0xd5, 0x16, 0xf6, 0x72, 0x87, 0x9f, 0x2e, 0x04, 0xda, 0x22, 0xbf, 0xe7, 0x89, 0xca, - 0x8a, 0x61, 0x23, 0xda, 0x92, 0x3f, 0xc4, 0xe8, 0x5e, 0x42, 0xe3, 0xa5, 0x76, 0xbb, 0x69, 0x12, - 0x03, 0xf4, 0x45, 0xeb, 0x34, 0x89, 0xcb, 0x5d, 0x7e, 0xe0, 0x31, 0x88, 0xce, 0x90, 0x75, 0x78, - 0xd3, 0x59, 0x77, 0x3a, 0xb2, 0x7f, 0x66, 0xbc, 0xac, 0xfa, 0x83, 0x69, 0x74, 0x76, 0xda, 0x21, - 0xba, 0x47, 0x16, 0x66, 0x4b, 0xa5, 0x0e, 0xf8, 0xc8, 0x35, 0x9b, 0xc4, 0x5a, 0x3b, 0x9a, 0x61, - 0xfd, 0x09, 0x34, 0x1a, 0x34, 0xa0, 0xd6, 0xb0, 0xdb, 0x44, 0x7c, 0x58, 0xd5, 0xf0, 0x31, 0x75, - 0x97, 0xa2, 0xb4, 0x08, 0x29, 0xbe, 0x8d, 0x4e, 0x05, 0x90, 0x52, 0xb3, 0x69, 0x6f, 0x6a, 0xa4, - 0xe3, 0x32, 0xc7, 0xd8, 0x3c, 0x73, 0x8c, 0x0d, 0x39, 0xe8, 0x14, 0x5f, 0x77, 0x28, 0x81, 0x96, - 0x54, 0x4a, 0xfd, 0xf1, 0x0c, 0x3a, 0x77, 0x57, 0x6f, 0x9a, 0x46, 0x28, 0x1a, 0x8d, 0xb8, 0x6d, - 0xdb, 0x72, 0xc9, 0x31, 0x1a, 0xa5, 0xd2, 0x50, 0xc8, 0x3e, 0x94, 0xa1, 0x10, 0xef, 0xa2, 0xfe, - 0x43, 0x77, 0x51, 0xee, 0x40, 0x5d, 0xf4, 0x5f, 0x53, 0xa8, 0xe0, 0x3b, 0xfe, 0x8b, 0x2f, 0xa1, - 0x05, 0xaf, 0x74, 0x38, 0x42, 0x8c, 0xf8, 0x41, 0x03, 0x1e, 0xd7, 0xd0, 0xc0, 0xcc, 0x83, 0xb6, - 0xe9, 0x10, 0x77, 0x0f, 0x4e, 0xdc, 0x17, 0xf9, 0x71, 0xc9, 0x38, 0x61, 0x45, 0x62, 0x27, 0x25, - 0x0c, 0x0c, 0xcf, 0xf9, 0xd8, 0xd3, 0x87, 0x29, 0xff, 0x79, 0x37, 0x7b, 0xce, 0xc7, 0x9f, 0x48, - 0x48, 0x6f, 0x2b, 0x43, 0x52, 0xfc, 0x24, 0xca, 0x2c, 0x2f, 0xcf, 0xf3, 0x99, 0x14, 0x9e, 0xd5, - 0x7b, 0x9e, 0xf8, 0x5e, 0x91, 0x62, 0xd5, 0xdf, 0x4b, 0x23, 0x44, 0x55, 0x81, 0x0d, 0xd7, 0x23, - 0x51, 0xc2, 0x29, 0x94, 0xf7, 0x05, 0xce, 0xd5, 0x30, 0xf0, 0xda, 0x8f, 0x76, 0x44, 0xb4, 0xee, - 0xe0, 0x85, 0x46, 0xd1, 0x77, 0x24, 0x67, 0xf7, 0x00, 0xb0, 0xb3, 0x01, 0x47, 0x72, 0xdf, 0x7d, - 0xfc, 0xa3, 0x68, 0x90, 0xcf, 0x78, 0xb6, 0x74, 0xfe, 0xdf, 0xf0, 0x81, 0x5a, 0x88, 0x8f, 0x4c, - 0xad, 0xb9, 0x43, 0x2c, 0xc4, 0xbe, 0x78, 0x59, 0xaf, 0x9c, 0x88, 0xf7, 0x21, 0x8b, 0xf7, 0x8b, - 0x5c, 0xbc, 0xec, 0x05, 0xcf, 0xb1, 0x15, 0xef, 0x43, 0x3b, 0xfb, 0x56, 0x7f, 0x27, 0x85, 0x30, - 0x6d, 0x56, 0x55, 0x77, 0xdd, 0x4d, 0xdb, 0x31, 0x98, 0x73, 0xfa, 0x91, 0x08, 0xe6, 0xe1, 0xdd, - 0x57, 0x7e, 0x35, 0x8f, 0x4e, 0x49, 0x8e, 0xbf, 0xc7, 0x7c, 0xb2, 0xba, 0x2a, 0x8f, 0xa6, 0x5e, - 0xaf, 0x5e, 0x3e, 0x24, 0x5e, 0x88, 0xf6, 0x4b, 0x0f, 0xd0, 0x84, 0x9b, 0xd0, 0xa7, 0xd1, 0x30, - 0xff, 0x41, 0x57, 0x68, 0xff, 0xa6, 0x0b, 0x46, 0xa9, 0x4b, 0x01, 0x9a, 0x84, 0xc6, 0xcf, 0xa1, - 0x41, 0x3a, 0x60, 0xd6, 0x20, 0x02, 0xc7, 0x40, 0xf8, 0xa2, 0xc4, 0xf0, 0x81, 0xe2, 0x7a, 0x12, - 0x50, 0x0a, 0xef, 0x88, 0xf2, 0x7b, 0x78, 0x47, 0xf4, 0x36, 0x1a, 0x2a, 0x59, 0x96, 0xed, 0xc1, - 0x26, 0xdd, 0xe5, 0x57, 0x13, 0x5d, 0xad, 0xf2, 0x27, 0xe1, 0x71, 0x7c, 0x48, 0x9f, 0x68, 0x96, - 0x8b, 0x0c, 0xf1, 0x0d, 0xff, 0x55, 0x0c, 0x71, 0xb8, 0x57, 0x39, 0x5c, 0xcf, 0x38, 0x1c, 0x16, - 0x7f, 0x14, 0x03, 0x9d, 0x37, 0x52, 0x75, 0xec, 0xb6, 0xed, 0x12, 0x83, 0x09, 0x6a, 0x28, 0x0c, - 0xdd, 0xd1, 0xe6, 0x08, 0x78, 0xc7, 0x26, 0x45, 0xc3, 0x90, 0x8a, 0xe0, 0x55, 0x74, 0xda, 0xbf, - 0x28, 0x0e, 0x5e, 0x0c, 0x56, 0xca, 0xae, 0x32, 0x0c, 0xaf, 0x92, 0x70, 0x54, 0x19, 0x2a, 0xe5, - 0xa9, 0x4b, 0xfe, 0xb5, 0x88, 0xff, 0xe4, 0xb0, 0x6e, 0x1a, 0x62, 0x57, 0x27, 0xf2, 0xc3, 0xdf, - 0x8a, 0x86, 0x16, 0xf4, 0x07, 0xe5, 0x0e, 0x3f, 0x7b, 0x19, 0xd9, 0xfb, 0xed, 0x4b, 0x4b, 0x7f, - 0x50, 0x37, 0x78, 0xb9, 0x88, 0x4d, 0x21, 0xb2, 0xc4, 0x75, 0x74, 0xb6, 0xea, 0xd8, 0x2d, 0xdb, - 0x23, 0x46, 0xe4, 0xf1, 0xdd, 0x58, 0xf8, 0x5a, 0xb7, 0xcd, 0x29, 0xea, 0x3d, 0x5e, 0xe1, 0x75, - 0x61, 0x83, 0x5b, 0x68, 0xac, 0xe4, 0xba, 0x9d, 0x16, 0x09, 0x6f, 0xa8, 0x0a, 0xbb, 0x7e, 0xc6, - 0x47, 0xb8, 0xd7, 0xf2, 0x63, 0x3a, 0x14, 0x65, 0x17, 0x54, 0x75, 0xcf, 0x14, 0x6b, 0x84, 0x6f, - 0x89, 0xf2, 0x7e, 0x3d, 0x9b, 0x1f, 0x2d, 0x8c, 0x69, 0xe7, 0xe2, 0x8d, 0x59, 0x36, 0xbd, 0x26, - 0x51, 0x7f, 0x35, 0x85, 0x50, 0x28, 0x60, 0xfc, 0xb4, 0x1c, 0xe6, 0x27, 0x15, 0x5e, 0x74, 0xf0, - 0xe8, 0x05, 0x52, 0x5c, 0x1f, 0x7c, 0x01, 0x65, 0x21, 0x3a, 0x45, 0x3a, 0x3c, 0x58, 0xdd, 0x30, - 0x2d, 0x43, 0x03, 0x28, 0xc5, 0x0a, 0x4f, 0xd1, 0x01, 0x0b, 0x97, 0xfa, 0xcc, 0x2a, 0x2c, 0xa3, - 0xb1, 0x5a, 0x67, 0xc5, 0xaf, 0x5b, 0x78, 0x57, 0x07, 0x41, 0x32, 0xdc, 0xce, 0x4a, 0xf0, 0x18, - 0x55, 0x0a, 0x41, 0x22, 0x17, 0x51, 0x7f, 0x36, 0x15, 0x99, 0x05, 0x8f, 0x70, 0xd1, 0xfb, 0x50, - 0xdc, 0x4f, 0x23, 0x3e, 0x2d, 0xa9, 0x7f, 0x3d, 0x8d, 0x86, 0xaa, 0xb6, 0xe3, 0xf1, 0x70, 0x1f, - 0xc7, 0x7b, 0x15, 0x12, 0xf6, 0x4a, 0xd9, 0x7d, 0xec, 0x95, 0x2e, 0xa0, 0xac, 0xe0, 0xa2, 0xcc, - 0xee, 0x45, 0x0c, 0xc3, 0xd1, 0x00, 0xaa, 0x7e, 0x5b, 0x1a, 0xa1, 0x4f, 0x3d, 0xf3, 0xcc, 0x23, - 0x2c, 0x20, 0xf5, 0x47, 0x53, 0x68, 0x8c, 0x5f, 0xd4, 0x09, 0x01, 0xb3, 0x06, 0xfc, 0x2b, 0x56, - 0x71, 0x5c, 0x32, 0x90, 0xe6, 0xe3, 0xe8, 0x12, 0x30, 0xf3, 0xc0, 0xf4, 0xe0, 0xae, 0x42, 0x88, - 0x98, 0x45, 0x38, 0x4c, 0x5c, 0x02, 0x7c, 0x3a, 0xfc, 0xb4, 0x7f, 0x05, 0x99, 0x09, 0xd7, 0x3d, - 0x5a, 0x60, 0x26, 0xf1, 0x1a, 0x52, 0xfd, 0x85, 0x2c, 0xca, 0xce, 0x3c, 0x20, 0x8d, 0x63, 0xde, - 0x35, 0xc2, 0xc1, 0x66, 0xf6, 0x90, 0x07, 0x9b, 0x07, 0xf1, 0xa9, 0x78, 0x35, 0xec, 0xcf, 0x9c, - 0x5c, 0x7d, 0xa4, 0xe7, 0xa3, 0xd5, 0xfb, 0x3d, 0x7d, 0xfc, 0x5c, 0x72, 0xfe, 0x49, 0x06, 0x65, - 0x6a, 0xd3, 0xd5, 0x13, 0xbd, 0x39, 0x52, 0xbd, 0xe9, 0x7d, 0x67, 0xad, 0x06, 0xd7, 0x50, 0xf9, - 0xd0, 0x4b, 0x34, 0x72, 0xe3, 0xf4, 0x8d, 0x0c, 0x1a, 0xad, 0xcd, 0x2e, 0x57, 0x85, 0x93, 0xe0, - 0xdb, 0xcc, 0x93, 0x0f, 0x7c, 0xca, 0x58, 0x97, 0x5e, 0x88, 0xd9, 0x33, 0x77, 0x2a, 0x96, 0xf7, - 0xfc, 0xcd, 0xbb, 0x7a, 0xb3, 0x43, 0xe0, 0xe8, 0x85, 0xf9, 0xfd, 0xba, 0xe6, 0xbb, 0xe4, 0xc7, - 0xe1, 0xe1, 0xbf, 0xcf, 0x00, 0x7f, 0x02, 0x65, 0xee, 0x70, 0x8f, 0x8c, 0x6e, 0x7c, 0x9e, 0xbd, - 0xc1, 0xf8, 0xd0, 0x49, 0x30, 0xd3, 0x31, 0x0d, 0xe0, 0x40, 0x4b, 0xd1, 0xc2, 0xb7, 0xf8, 0x02, - 0xbc, 0xa7, 0xc2, 0x6b, 0x7e, 0xe1, 0x5b, 0x95, 0x32, 0xae, 0xa1, 0xa1, 0x2a, 0x71, 0x5a, 0x26, - 0x74, 0x94, 0x3f, 0x67, 0xf7, 0x66, 0x42, 0x77, 0x2a, 0x43, 0xed, 0xb0, 0x10, 0x30, 0x13, 0xb9, - 0xe0, 0x37, 0x11, 0x62, 0x36, 0xca, 0x1e, 0x83, 0x30, 0x5e, 0x04, 0xbb, 0x9f, 0x99, 0x96, 0x09, - 0x36, 0x9e, 0xc0, 0x0c, 0x6f, 0xa0, 0xc2, 0x82, 0x6d, 0x98, 0xab, 0x26, 0x73, 0xbd, 0x84, 0x0a, - 0x72, 0xbb, 0x3b, 0x3c, 0x51, 0x53, 0xb2, 0x25, 0x94, 0x4b, 0xaa, 0x26, 0xc6, 0x58, 0xfd, 0x87, - 0xfd, 0x28, 0x4b, 0xbb, 0xfd, 0x64, 0xfc, 0x1e, 0x66, 0xfc, 0x96, 0x50, 0xe1, 0x9e, 0xed, 0x6c, - 0x98, 0xd6, 0x5a, 0xe0, 0x15, 0xcf, 0xf7, 0xa6, 0xe0, 0xc9, 0xb3, 0xc9, 0x70, 0xf5, 0xc0, 0x81, - 0x5e, 0x8b, 0x91, 0xef, 0x32, 0x82, 0x5f, 0x44, 0x88, 0xbd, 0x75, 0x07, 0x9a, 0x7c, 0x18, 0xac, - 0x82, 0xbd, 0x84, 0x07, 0x47, 0x7b, 0x31, 0x58, 0x45, 0x48, 0x4c, 0x37, 0xe1, 0xcc, 0x17, 0x62, - 0x10, 0xfc, 0xee, 0x61, 0x13, 0x0e, 0xbe, 0x10, 0xa2, 0x11, 0xc0, 0xbc, 0x22, 0xaa, 0x08, 0x09, - 0xf7, 0x4b, 0x28, 0x22, 0x08, 0x69, 0x72, 0xe0, 0xe1, 0xe1, 0x12, 0xae, 0x97, 0x34, 0x81, 0x07, - 0x7e, 0x3e, 0x72, 0x01, 0x8e, 0x25, 0x6e, 0x5d, 0xef, 0xbf, 0x43, 0x07, 0xaa, 0xe1, 0xdd, 0x1c, - 0xa8, 0xd4, 0x2f, 0xa4, 0xd1, 0x60, 0xad, 0xb3, 0xe2, 0x6e, 0xb9, 0x1e, 0x69, 0x1d, 0x73, 0x35, - 0xf6, 0xb7, 0x57, 0xd9, 0xc4, 0xed, 0xd5, 0x93, 0xbe, 0x50, 0x84, 0x73, 0xc7, 0xc0, 0xa4, 0xf3, - 0xc5, 0xf1, 0xf7, 0xd2, 0xa8, 0xc0, 0x2e, 0xce, 0xca, 0xa6, 0xdb, 0x78, 0x08, 0xce, 0xfc, 0x47, - 0x2f, 0x95, 0xc3, 0x5d, 0x36, 0xef, 0xe1, 0x89, 0x84, 0xfa, 0xb9, 0x34, 0x1a, 0x2a, 0x75, 0xbc, - 0xf5, 0x92, 0x07, 0xba, 0xf5, 0x48, 0xee, 0x4f, 0x7e, 0x23, 0x85, 0xc6, 0x68, 0x43, 0x96, 0xed, - 0x0d, 0x62, 0x3d, 0x84, 0x83, 0x47, 0xf1, 0x00, 0x31, 0x7d, 0xc0, 0x03, 0x44, 0x5f, 0x96, 0x99, - 0xfd, 0xc9, 0x12, 0x8e, 0xcb, 0x35, 0xbb, 0x49, 0x8e, 0xf7, 0x67, 0x3c, 0xc4, 0xe3, 0x72, 0x5f, - 0x20, 0x0f, 0xe1, 0x7a, 0xe6, 0x83, 0x25, 0x90, 0x87, 0x70, 0xb6, 0xf4, 0xc1, 0x10, 0xc8, 0x57, - 0x53, 0x68, 0x70, 0xca, 0xf6, 0x8e, 0xf9, 0xc0, 0xe7, 0x5f, 0x71, 0xbc, 0xd5, 0xdc, 0xff, 0x8a, - 0xe3, 0xad, 0x9b, 0xea, 0x0f, 0xa7, 0xd1, 0x69, 0x1e, 0x60, 0x9b, 0x9f, 0x3f, 0x9c, 0x4c, 0xc7, - 0x7c, 0xb0, 0xc5, 0x45, 0x73, 0x32, 0x0f, 0x71, 0xd1, 0xfc, 0x64, 0x06, 0x9d, 0x86, 0x50, 0xa6, - 0x74, 0x5b, 0xf6, 0x01, 0xb0, 0x45, 0x70, 0x43, 0xbe, 0x04, 0x5d, 0x48, 0xb8, 0x04, 0xfd, 0x93, - 0xed, 0xe2, 0xf3, 0x6b, 0xa6, 0xb7, 0xde, 0x59, 0x99, 0x6c, 0xd8, 0xad, 0xeb, 0x6b, 0x8e, 0x7e, - 0xdf, 0x64, 0xd7, 0x7f, 0x7a, 0xf3, 0x7a, 0x90, 0xab, 0x42, 0x6f, 0x9b, 0x3c, 0x8b, 0x45, 0x0d, - 0xf6, 0x3a, 0x94, 0xab, 0x7f, 0x7d, 0xea, 0x22, 0xf4, 0xba, 0x6d, 0x5a, 0xdc, 0xa7, 0x90, 0x19, - 0xba, 0x35, 0xba, 0x3f, 0x7c, 0xc7, 0x36, 0xad, 0x7a, 0xd4, 0xb1, 0x70, 0xbf, 0xf5, 0x85, 0xac, - 0x35, 0xa1, 0x1a, 0xf5, 0x5f, 0xa5, 0xd0, 0x79, 0x59, 0x8b, 0x3f, 0x08, 0xb6, 0xe3, 0x8f, 0xa4, - 0xd1, 0x99, 0x5b, 0x20, 0x9c, 0xc0, 0x91, 0xe3, 0x64, 0xde, 0xe2, 0x83, 0x33, 0x41, 0x36, 0x27, - 0x16, 0x65, 0x77, 0xd9, 0x9c, 0x4c, 0xea, 0x5c, 0x36, 0xbf, 0x99, 0x42, 0xa7, 0x96, 0x2a, 0xe5, - 0xe9, 0x0f, 0xc8, 0x88, 0x8a, 0x7f, 0xcf, 0x31, 0x37, 0x38, 0x63, 0xdf, 0x73, 0xcc, 0x4d, 0x4f, - 0xfa, 0x3d, 0xb5, 0xd2, 0xc2, 0xfc, 0x07, 0x49, 0xdf, 0xa4, 0xef, 0xf9, 0x00, 0xe8, 0x9b, 0xf4, - 0x3d, 0xc7, 0x5c, 0xdf, 0xfe, 0x71, 0x0e, 0x0d, 0xdd, 0xee, 0xac, 0x10, 0xee, 0x12, 0xf2, 0x48, - 0x9f, 0xb7, 0xde, 0x40, 0x43, 0x5c, 0x0c, 0x70, 0x57, 0x21, 0x84, 0xac, 0xe3, 0x21, 0x48, 0x58, - 0x54, 0x20, 0x91, 0x08, 0x5f, 0x40, 0xd9, 0xbb, 0xc4, 0x59, 0x11, 0x5f, 0x73, 0xde, 0x27, 0xce, - 0x8a, 0x06, 0x50, 0x3c, 0x1f, 0x3a, 0xaa, 0x97, 0xaa, 0x15, 0x48, 0x5f, 0xc2, 0xaf, 0x49, 0x20, - 0x1f, 0x4b, 0xe0, 0x6d, 0xa6, 0xb7, 0x4d, 0x96, 0xf8, 0x44, 0x7c, 0x49, 0x1e, 0x2d, 0x89, 0x17, - 0xd1, 0xb8, 0xe8, 0x6e, 0xc4, 0x72, 0x77, 0xe4, 0x13, 0xd8, 0x25, 0x65, 0xed, 0x88, 0x17, 0xc5, - 0xaf, 0xa2, 0x61, 0x1f, 0x08, 0x8e, 0x53, 0x83, 0x61, 0xc0, 0xf8, 0x80, 0x55, 0x24, 0xa9, 0x8f, - 0x54, 0x40, 0x64, 0x00, 0x87, 0xff, 0x28, 0x81, 0x41, 0xc4, 0x11, 0x4d, 0x2a, 0x80, 0x9f, 0x03, - 0x06, 0xf0, 0xb8, 0x02, 0x5c, 0x44, 0x86, 0xe0, 0xa9, 0x23, 0x38, 0xc2, 0x3b, 0x1c, 0xce, 0x1e, - 0xb4, 0x4a, 0x64, 0x78, 0x09, 0xa1, 0xf0, 0x2a, 0x9f, 0x87, 0x0d, 0xd8, 0xb7, 0x93, 0x81, 0xc0, - 0x42, 0xbc, 0x84, 0x1b, 0x39, 0xc8, 0x25, 0x9c, 0xfa, 0xdb, 0x69, 0x34, 0x54, 0x6a, 0xb7, 0x83, - 0xa1, 0xf0, 0x34, 0xca, 0x95, 0xda, 0xed, 0x3b, 0x5a, 0x45, 0x0c, 0x20, 0xae, 0xb7, 0xdb, 0xf5, - 0x8e, 0x63, 0x8a, 0x9e, 0x98, 0x8c, 0x08, 0x4f, 0xa3, 0x91, 0x52, 0xbb, 0x5d, 0xed, 0xac, 0x34, - 0xcd, 0x86, 0x90, 0x8f, 0x88, 0xa5, 0x3d, 0x6b, 0xb7, 0xeb, 0x6d, 0xc0, 0x44, 0x13, 0x4a, 0xc9, - 0x65, 0xf0, 0xdb, 0x10, 0x6c, 0x87, 0xa7, 0xc3, 0x61, 0x09, 0x37, 0xd4, 0x20, 0x74, 0x78, 0xd8, - 0xb6, 0xc9, 0x80, 0x88, 0x85, 0x58, 0xbf, 0xe0, 0x07, 0xaa, 0xa7, 0x15, 0xc5, 0xd2, 0xde, 0x84, - 0x2c, 0xf1, 0xc7, 0xd0, 0x40, 0xa9, 0xdd, 0x16, 0x6e, 0x79, 0xc0, 0x95, 0x87, 0x96, 0x8a, 0xf4, - 0xb1, 0x4f, 0x36, 0xf1, 0x32, 0x1a, 0x95, 0x2b, 0xdb, 0x57, 0x88, 0xf6, 0x3f, 0x4e, 0xc1, 0x07, - 0x1d, 0x73, 0x4f, 0xe2, 0x67, 0x51, 0xa6, 0xd4, 0x6e, 0xf3, 0xf9, 0xe8, 0x54, 0x42, 0x7f, 0x44, - 0x1f, 0x1e, 0x97, 0xda, 0x6d, 0xff, 0xd3, 0x8f, 0xf9, 0x93, 0x84, 0x03, 0x7d, 0xfa, 0x57, 0xd9, - 0xa7, 0x1f, 0xef, 0xe7, 0x02, 0xea, 0x2f, 0x64, 0xd0, 0x58, 0xa9, 0xdd, 0x3e, 0x09, 0xed, 0xfe, - 0xb0, 0x9e, 0x37, 0x3f, 0x83, 0x90, 0x30, 0x3d, 0x0e, 0x04, 0x0f, 0xa6, 0x86, 0x84, 0xa9, 0x51, - 0x49, 0x69, 0x02, 0x91, 0xaf, 0x7e, 0xf9, 0x7d, 0xa9, 0xdf, 0xe7, 0x32, 0x30, 0x15, 0x1f, 0xf7, - 0x50, 0x4d, 0xef, 0x97, 0x6e, 0xe3, 0x7d, 0x90, 0xdb, 0x57, 0x1f, 0xfc, 0xba, 0x34, 0x78, 0x20, - 0x54, 0xf8, 0x49, 0x2f, 0xf4, 0x1f, 0xca, 0x2c, 0x1e, 0x15, 0x85, 0xc9, 0xe3, 0xc7, 0xf8, 0xe9, - 0x8b, 0x78, 0x34, 0xa3, 0x06, 0x45, 0xd5, 0x4d, 0x43, 0x8b, 0xd0, 0xfa, 0x7d, 0x38, 0xb0, 0xaf, - 0x3e, 0xdc, 0x4e, 0xc3, 0x8b, 0xe5, 0x20, 0x1a, 0xd2, 0xe1, 0x77, 0x17, 0xd7, 0x11, 0x62, 0xf7, - 0xfd, 0x81, 0x33, 0xf1, 0x08, 0x0b, 0x7c, 0xc2, 0xb2, 0x1a, 0xf1, 0xc0, 0x27, 0x21, 0x49, 0xe0, - 0x97, 0x94, 0x49, 0xf4, 0x4b, 0xba, 0x8a, 0xf2, 0x9a, 0xbe, 0xf9, 0x46, 0x87, 0x38, 0x5b, 0xdc, - 0x9c, 0x61, 0xc1, 0x06, 0xf5, 0xcd, 0xfa, 0x67, 0x29, 0x50, 0x0b, 0xd0, 0x58, 0x0d, 0x9e, 0xbc, - 0x0b, 0x7e, 0x18, 0xec, 0x64, 0x3a, 0x78, 0xe8, 0x7e, 0x10, 0x45, 0xc7, 0x2f, 0xa1, 0x4c, 0xe9, - 0x5e, 0x8d, 0x4b, 0x36, 0xe8, 0xda, 0xd2, 0xbd, 0x1a, 0x97, 0x57, 0xd7, 0xb2, 0xf7, 0x6a, 0xea, - 0xe7, 0xd2, 0x08, 0xc7, 0x29, 0xf1, 0xf3, 0x68, 0x10, 0xa0, 0x6b, 0x54, 0x67, 0xc4, 0x74, 0x98, - 0x9b, 0x6e, 0xdd, 0x01, 0xa8, 0x64, 0xdc, 0xf9, 0xa4, 0xf8, 0x45, 0xc8, 0xda, 0xcb, 0x13, 0xb2, - 0x49, 0xe9, 0x30, 0x37, 0x5d, 0x3f, 0xcf, 0x6d, 0x24, 0x69, 0x2f, 0x27, 0x06, 0xbb, 0xf0, 0x5e, - 0x6d, 0xce, 0x76, 0x3d, 0x2e, 0x6a, 0x66, 0x17, 0x6e, 0xba, 0x90, 0x43, 0x55, 0xb2, 0x0b, 0x19, - 0x19, 0xe4, 0x92, 0xba, 0x57, 0x63, 0x8f, 0x43, 0x0c, 0xcd, 0x6e, 0xfa, 0x06, 0x25, 0xcb, 0x25, - 0xb5, 0xe9, 0xd6, 0xd9, 0xc3, 0x12, 0x03, 0xd2, 0x05, 0x4b, 0xb9, 0xa4, 0xa4, 0x52, 0xea, 0xf7, - 0xe5, 0x51, 0xa1, 0xac, 0x7b, 0xfa, 0x8a, 0xee, 0x12, 0x61, 0x37, 0x3d, 0xe6, 0xc3, 0xfc, 0xcf, - 0x11, 0xe4, 0x60, 0xac, 0x24, 0x7c, 0x4d, 0xb4, 0x00, 0xfe, 0x44, 0xc8, 0x37, 0xc8, 0xf4, 0x29, - 0xa6, 0x0e, 0x5b, 0xa9, 0xb7, 0x39, 0x58, 0x8b, 0x11, 0xe2, 0x6b, 0x68, 0xc8, 0x87, 0xd1, 0x0d, - 0x40, 0x26, 0xd4, 0x19, 0x63, 0x85, 0xda, 0xff, 0x9a, 0x88, 0xc6, 0x2f, 0xa2, 0x61, 0xff, 0xa7, - 0x60, 0x5a, 0xb3, 0x3c, 0x68, 0x2b, 0xb1, 0xdd, 0x93, 0x48, 0x2a, 0x16, 0x85, 0xf9, 0xad, 0x5f, - 0x2a, 0x1a, 0x49, 0x35, 0x26, 0x91, 0xe2, 0xcf, 0xa2, 0x51, 0xff, 0x37, 0xdf, 0x30, 0xb0, 0xac, - 0x6c, 0xd7, 0x82, 0x6c, 0xc4, 0x11, 0xb1, 0x4e, 0xca, 0xe4, 0x6c, 0xeb, 0xf0, 0x98, 0x9f, 0x3d, - 0xcb, 0x58, 0x89, 0xef, 0x1c, 0x22, 0x15, 0xe0, 0x0a, 0x1a, 0xf7, 0x21, 0xa1, 0x86, 0x0e, 0x84, - 0x3b, 0x46, 0x63, 0xa5, 0x9e, 0xa8, 0xa4, 0xf1, 0x52, 0xb8, 0x89, 0x2e, 0x48, 0x40, 0xc3, 0x5d, - 0x37, 0x57, 0x3d, 0xbe, 0xdd, 0xe3, 0x91, 0x7f, 0x79, 0xba, 0xc4, 0x80, 0x2b, 0xa3, 0xf1, 0xf3, - 0x9e, 0xca, 0x39, 0x99, 0x7a, 0x72, 0xc3, 0x35, 0x74, 0xda, 0xc7, 0xdf, 0x9a, 0xae, 0x56, 0x1d, - 0xfb, 0x1d, 0xd2, 0xf0, 0x2a, 0x65, 0xbe, 0x5d, 0x86, 0x88, 0x70, 0xc6, 0x4a, 0x7d, 0xad, 0xd1, - 0xa6, 0x4a, 0x41, 0x71, 0x32, 0xf3, 0xc4, 0xc2, 0xf8, 0x2e, 0x3a, 0x23, 0xc0, 0x2b, 0x96, 0xeb, - 0xe9, 0x56, 0x83, 0x54, 0xca, 0x7c, 0x0f, 0x0d, 0xfb, 0x79, 0xce, 0xd5, 0xe4, 0x48, 0x99, 0x6d, - 0x72, 0x71, 0xfc, 0x32, 0x1a, 0xf1, 0x11, 0xec, 0xee, 0x6e, 0x08, 0xee, 0xee, 0x60, 0x48, 0x1a, - 0x2b, 0xf5, 0xe8, 0x1b, 0x46, 0x99, 0x58, 0xd4, 0x28, 0x48, 0x06, 0x3f, 0x2c, 0x69, 0x94, 0xb7, - 0xd5, 0x4e, 0x54, 0x46, 0x48, 0x10, 0xff, 0x6a, 0xa8, 0x51, 0x4b, 0x8e, 0xb9, 0x66, 0xb2, 0x9d, - 0xb4, 0xff, 0x6c, 0x71, 0xa5, 0x6e, 0x03, 0x30, 0x49, 0x3f, 0x18, 0xf9, 0x44, 0x09, 0x9d, 0x4a, - 0xd0, 0xb1, 0x7d, 0xed, 0x18, 0xbf, 0x90, 0x0e, 0x1b, 0x71, 0xcc, 0xb7, 0x8d, 0x53, 0x28, 0xef, - 0x7f, 0x09, 0x37, 0x1e, 0x94, 0x6e, 0x43, 0x33, 0xca, 0xc3, 0xc7, 0x4b, 0xe2, 0x38, 0xe6, 0x5b, - 0xc9, 0x87, 0x21, 0x8e, 0xf7, 0x52, 0xa1, 0x38, 0x8e, 0xf9, 0xf6, 0xf2, 0x37, 0x33, 0xe1, 0x9c, - 0x74, 0xb2, 0xc7, 0x7c, 0x58, 0x66, 0x72, 0xe8, 0x7d, 0x9a, 0xdb, 0xc7, 0xf3, 0x41, 0x51, 0x35, - 0x07, 0x0e, 0xa8, 0x9a, 0xbf, 0x1b, 0xef, 0x4f, 0x66, 0x7a, 0x1e, 0xcb, 0xfe, 0x7c, 0x08, 0x83, - 0x15, 0xdf, 0x08, 0xd7, 0x31, 0x66, 0xa3, 0xf7, 0x0b, 0x81, 0xf5, 0x56, 0xb8, 0x89, 0x2e, 0x93, - 0xe0, 0x4f, 0xa3, 0x73, 0x12, 0xa0, 0xaa, 0x3b, 0x7a, 0x8b, 0x78, 0x61, 0x9e, 0x3f, 0x08, 0x95, - 0xe4, 0x97, 0xae, 0xb7, 0x03, 0xb4, 0x98, 0x3b, 0xb0, 0x0b, 0x07, 0x41, 0x39, 0x06, 0xf6, 0xe1, - 0x9a, 0xfc, 0x6f, 0xb3, 0x48, 0x09, 0x0c, 0xc4, 0xe0, 0x11, 0xce, 0x11, 0x4e, 0xc6, 0xef, 0x8b, - 0xce, 0x35, 0xd1, 0x78, 0x28, 0x8c, 0x5a, 0xa7, 0xd5, 0xd2, 0xa1, 0x83, 0xa9, 0x01, 0x5a, 0x8c, - 0x32, 0x0b, 0x09, 0x99, 0xcd, 0x39, 0xc1, 0x6d, 0x4e, 0x1c, 0x3e, 0x72, 0xaa, 0xbb, 0x8c, 0x85, - 0x16, 0xe7, 0x8a, 0xbf, 0x98, 0x42, 0xa7, 0x4b, 0xab, 0xab, 0xa4, 0xe1, 0x11, 0x63, 0x69, 0x85, - 0x1a, 0x5f, 0xd3, 0x76, 0xc7, 0xf2, 0x7c, 0x7b, 0xf7, 0xa5, 0xee, 0xd5, 0xb1, 0x4e, 0x9a, 0x4c, - 0x2a, 0xcc, 0x5a, 0x12, 0x04, 0x0d, 0xd0, 0x39, 0x49, 0xdd, 0x06, 0x9a, 0x7a, 0x03, 0x88, 0xb4, - 0xc4, 0x7a, 0x27, 0x6e, 0xa1, 0xf3, 0x5d, 0x59, 0xee, 0x66, 0xec, 0xf4, 0x8b, 0xc6, 0xce, 0xbf, - 0x49, 0x85, 0xea, 0x1e, 0x11, 0x12, 0x9e, 0x44, 0x28, 0x04, 0xf1, 0xed, 0xcf, 0xe8, 0xce, 0x76, - 0x11, 0x85, 0x42, 0xd3, 0x04, 0x0a, 0xbc, 0x84, 0x72, 0x5c, 0x2c, 0x2c, 0x73, 0xeb, 0x47, 0x77, - 0xe9, 0x85, 0x49, 0x51, 0x0e, 0xb0, 0xb5, 0xe1, 0xdf, 0xcc, 0xd9, 0x4c, 0xbc, 0x88, 0x86, 0x0e, - 0xfa, 0x5d, 0x5f, 0xcc, 0x20, 0x2c, 0xee, 0x55, 0x8e, 0xd0, 0x90, 0x7b, 0x5f, 0x0c, 0x96, 0x83, - 0x65, 0x5e, 0xb9, 0x82, 0xf2, 0xf4, 0x13, 0x20, 0x97, 0x81, 0x10, 0xbb, 0xb4, 0xc3, 0x61, 0x5a, - 0x80, 0x0d, 0x03, 0x07, 0x0d, 0x24, 0x07, 0x0e, 0x52, 0x7f, 0x20, 0x83, 0xce, 0x8a, 0x1d, 0x52, - 0x26, 0x10, 0x0e, 0xfd, 0xa4, 0x53, 0xbe, 0x89, 0x9d, 0xa2, 0xa2, 0x1c, 0x33, 0x51, 0x79, 0x5c, - 0x7a, 0x76, 0x7c, 0x00, 0x10, 0x8d, 0x63, 0xd4, 0xff, 0x94, 0x46, 0x23, 0x55, 0xdb, 0xf5, 0xd6, - 0x1c, 0xe2, 0x56, 0x75, 0xc7, 0x7d, 0x84, 0xbb, 0xe3, 0xe3, 0x68, 0x04, 0x42, 0xbf, 0xb4, 0x88, - 0xc5, 0xc2, 0xa3, 0xf4, 0x0b, 0x89, 0x24, 0x7c, 0x04, 0xcf, 0x19, 0x24, 0x11, 0x52, 0xed, 0x67, - 0xf6, 0x85, 0x10, 0x90, 0x87, 0x19, 0x17, 0x0c, 0xae, 0xfe, 0x8d, 0x0c, 0x1a, 0xf6, 0xa5, 0x3c, - 0x65, 0x1e, 0xd7, 0xfb, 0x80, 0xa3, 0x15, 0xf2, 0x75, 0x84, 0xaa, 0xb6, 0xe3, 0xe9, 0xcd, 0xc5, - 0x50, 0xf3, 0xe1, 0x20, 0xad, 0x0d, 0x50, 0x56, 0x46, 0x20, 0x81, 0xf5, 0x2b, 0x34, 0xde, 0xd8, - 0xc4, 0xc4, 0xd6, 0xaf, 0x00, 0xaa, 0x09, 0x14, 0xea, 0xaf, 0xa4, 0xd1, 0x98, 0xdf, 0x49, 0x33, - 0x0f, 0x48, 0xa3, 0xf3, 0x28, 0xcf, 0x4d, 0xb2, 0xb4, 0xfb, 0x77, 0x95, 0xb6, 0xfa, 0xdf, 0x85, - 0x89, 0x64, 0xba, 0x69, 0x9f, 0x4c, 0x24, 0x7f, 0x16, 0x3a, 0xae, 0x7e, 0x47, 0x06, 0x9d, 0xf6, - 0xa5, 0x3e, 0xdb, 0xb1, 0x60, 0x0b, 0x3a, 0xad, 0x37, 0x9b, 0x8f, 0xf2, 0x9e, 0x6f, 0xc8, 0x17, - 0xc4, 0x12, 0x8f, 0xa5, 0xc6, 0xf3, 0xb7, 0xad, 0x72, 0x70, 0xdd, 0x36, 0x0d, 0x4d, 0x24, 0xc2, - 0xaf, 0xa2, 0x61, 0xff, 0x67, 0xc9, 0x59, 0xf3, 0x37, 0x7a, 0x70, 0xa0, 0x1c, 0x14, 0xd2, 0x1d, - 0xe9, 0xc9, 0xb8, 0x54, 0x40, 0xfd, 0x2f, 0x39, 0x34, 0x71, 0xcf, 0xb4, 0x0c, 0x7b, 0xd3, 0xf5, - 0xd3, 0xff, 0x1d, 0xfb, 0x03, 0x95, 0xa3, 0x4e, 0xfb, 0xf7, 0x06, 0x3a, 0x13, 0x15, 0xa9, 0x13, - 0x04, 0x65, 0xe6, 0xbd, 0xb3, 0xc9, 0x08, 0xea, 0x7e, 0x22, 0x40, 0x7e, 0x2b, 0xa3, 0x25, 0x97, - 0x8c, 0x66, 0x12, 0x1c, 0xd8, 0x4b, 0x26, 0xc1, 0xa7, 0x50, 0xae, 0x6c, 0xb7, 0x74, 0xd3, 0x0f, - 0x1e, 0x02, 0xa3, 0x38, 0xa8, 0x17, 0x30, 0x1a, 0xa7, 0xa0, 0xfc, 0x79, 0xc5, 0xd0, 0x65, 0x83, - 0x21, 0x7f, 0xbf, 0x00, 0xb5, 0xd2, 0x34, 0x91, 0x08, 0xdb, 0x68, 0x84, 0x57, 0xc7, 0xef, 0x50, - 0x10, 0x6c, 0x9e, 0x9e, 0xf3, 0x65, 0xd4, 0x5d, 0xad, 0x26, 0xa5, 0x72, 0x6c, 0x1b, 0xc5, 0x12, - 0x1c, 0xf2, 0x8f, 0x61, 0xb7, 0x29, 0x9a, 0xcc, 0x5f, 0x10, 0x02, 0x4c, 0x32, 0x43, 0x71, 0x21, - 0xc0, 0x2c, 0x23, 0x12, 0xe1, 0x19, 0x34, 0x0e, 0xa1, 0x73, 0x83, 0xad, 0x14, 0x55, 0x89, 0x61, - 0x30, 0x2a, 0xe1, 0x68, 0x9e, 0x45, 0xdb, 0xa5, 0x1f, 0x57, 0x6f, 0x70, 0xb4, 0x16, 0x2f, 0x31, - 0xf1, 0x1a, 0xc2, 0xf1, 0x36, 0xef, 0xeb, 0x70, 0xfe, 0xfb, 0xd2, 0xe1, 0xbe, 0xee, 0xb8, 0xbb, - 0x57, 0x3c, 0x8c, 0xe3, 0xe8, 0x9f, 0x49, 0xa1, 0xf1, 0x58, 0x28, 0x66, 0xfc, 0x2c, 0x42, 0x0c, - 0x22, 0x84, 0xbc, 0x83, 0x18, 0x12, 0x61, 0x78, 0x66, 0xbe, 0x94, 0x84, 0x64, 0xf8, 0x3a, 0xca, - 0xb3, 0x5f, 0x3c, 0x4c, 0x4d, 0xbc, 0x48, 0xa7, 0x63, 0x1a, 0x5a, 0x40, 0x14, 0xd6, 0x02, 0xb7, - 0x3c, 0x99, 0xc4, 0x22, 0xde, 0x56, 0x3b, 0xa8, 0x85, 0x92, 0xd1, 0x0e, 0x1c, 0x0e, 0x1a, 0x5c, - 0x32, 0x8e, 0xaa, 0xeb, 0x72, 0x3c, 0xaa, 0x75, 0x66, 0xb7, 0xa8, 0xd6, 0x91, 0xb9, 0x89, 0x87, - 0xb1, 0x7e, 0x78, 0x4f, 0x43, 0xbe, 0x94, 0x46, 0x63, 0x41, 0xad, 0x47, 0x78, 0xa1, 0xf0, 0x3e, - 0x12, 0xc9, 0x17, 0x53, 0x48, 0x99, 0x32, 0x9b, 0x4d, 0xd3, 0x5a, 0xab, 0x58, 0xab, 0xb6, 0xd3, - 0x82, 0xc9, 0xe3, 0xe8, 0x8e, 0x3b, 0xd5, 0xef, 0x4e, 0xa1, 0x71, 0xde, 0xa0, 0x69, 0xdd, 0x31, - 0x8e, 0xee, 0x2c, 0x29, 0xda, 0x92, 0xa3, 0xd3, 0x17, 0xf5, 0x2b, 0x69, 0x84, 0xe6, 0xed, 0xc6, - 0xc6, 0x31, 0x7f, 0x1b, 0xf8, 0x09, 0x94, 0x63, 0xb1, 0x82, 0xb8, 0xc6, 0x8e, 0x4f, 0xb2, 0x27, - 0x9f, 0xf4, 0xd3, 0x18, 0x62, 0xaa, 0xc0, 0x4f, 0x68, 0x73, 0x2c, 0xd6, 0x90, 0x92, 0xd2, 0x78, - 0x11, 0x5a, 0x29, 0xa5, 0xe3, 0x56, 0x4d, 0x50, 0x29, 0x85, 0xc9, 0x95, 0xee, 0x6c, 0x17, 0xb3, - 0x4d, 0xbb, 0xb1, 0xa1, 0x01, 0xbd, 0xfa, 0xa7, 0x29, 0x26, 0xbb, 0x63, 0xfe, 0x3e, 0xce, 0xff, - 0xfc, 0xec, 0x3e, 0x3f, 0xff, 0x7b, 0x53, 0xe8, 0xb4, 0x46, 0x1a, 0xf6, 0x7d, 0xe2, 0x6c, 0x4d, - 0xdb, 0x06, 0xb9, 0x45, 0x2c, 0xe2, 0x1c, 0xd5, 0x88, 0xfa, 0x07, 0x90, 0x06, 0x20, 0x6c, 0xcc, - 0x1d, 0x97, 0x18, 0xc7, 0x27, 0x45, 0x83, 0xfa, 0xf7, 0x07, 0x90, 0x92, 0x68, 0x21, 0x1e, 0x5b, - 0xab, 0xa8, 0xab, 0xd9, 0x9f, 0x7d, 0x58, 0x66, 0x7f, 0xff, 0xfe, 0xcc, 0xfe, 0xdc, 0x7e, 0xcd, - 0xfe, 0x81, 0xbd, 0x98, 0xfd, 0xad, 0xa8, 0xd9, 0x9f, 0x07, 0xb3, 0xff, 0xd9, 0x9e, 0x66, 0xff, - 0x8c, 0x65, 0x1c, 0xd0, 0xe8, 0x3f, 0xb6, 0xe9, 0x43, 0x0f, 0xb2, 0x5b, 0xb9, 0x42, 0x27, 0xc5, - 0x86, 0xed, 0x18, 0xc4, 0xe0, 0x9b, 0x14, 0x38, 0x21, 0x77, 0x38, 0x4c, 0x0b, 0xb0, 0xb1, 0x5c, - 0xac, 0x23, 0x7b, 0xc9, 0xc5, 0xfa, 0x10, 0xb6, 0x31, 0x5f, 0x48, 0xa3, 0xf1, 0x69, 0xe2, 0x78, - 0x2c, 0x18, 0xe1, 0xc3, 0x70, 0x33, 0x2a, 0xa1, 0x31, 0x81, 0x21, 0x58, 0xe4, 0xe9, 0xd0, 0x75, - 0xaa, 0x41, 0x1c, 0x2f, 0xea, 0x79, 0x15, 0xa5, 0xa7, 0xd5, 0xfb, 0xf9, 0x90, 0xf8, 0xd8, 0x0d, - 0xaa, 0xf7, 0xe1, 0x4c, 0x90, 0x26, 0xff, 0xa5, 0x05, 0xf4, 0x42, 0x8a, 0xa3, 0xec, 0xfe, 0x53, - 0x1c, 0xa9, 0x3f, 0x9d, 0x42, 0x97, 0x35, 0x62, 0x91, 0x4d, 0x7d, 0xa5, 0x49, 0x84, 0x66, 0xf1, - 0x95, 0x81, 0xce, 0x1a, 0xa6, 0xdb, 0xd2, 0xbd, 0xc6, 0xfa, 0xa1, 0x64, 0x34, 0x8b, 0x86, 0xc5, - 0xf9, 0x6b, 0x1f, 0x73, 0x9b, 0x54, 0x4e, 0xfd, 0xe5, 0x0c, 0x1a, 0x98, 0xb2, 0xbd, 0xd7, 0xed, - 0x43, 0xe6, 0xdc, 0x0a, 0xa7, 0xfc, 0xf4, 0x3e, 0xce, 0x45, 0x3e, 0x06, 0x95, 0x0b, 0x61, 0xc8, - 0xc1, 0x2d, 0x6f, 0xc5, 0x8e, 0x85, 0x6b, 0xf7, 0xc9, 0xf6, 0x99, 0x6d, 0xeb, 0x79, 0x34, 0x08, - 0x71, 0x2c, 0x84, 0x93, 0x4b, 0x70, 0x7a, 0xf5, 0x28, 0x30, 0x5a, 0x47, 0x48, 0x8a, 0x3f, 0x2d, - 0x45, 0x4f, 0xcc, 0x1d, 0x3e, 0x3b, 0x97, 0x18, 0x48, 0xf1, 0xa1, 0x25, 0xc1, 0x52, 0xbf, 0x91, - 0x45, 0xc3, 0xbe, 0xab, 0xe3, 0x11, 0xf5, 0xe0, 0xd3, 0x28, 0x37, 0x67, 0x0b, 0x21, 0xd5, 0xc1, - 0x35, 0x72, 0xdd, 0x76, 0x23, 0x3e, 0x9f, 0x9c, 0x08, 0x3f, 0x8b, 0xf2, 0x8b, 0xb6, 0x21, 0x3a, - 0xf6, 0xc2, 0x98, 0xb6, 0x6c, 0x23, 0xf6, 0x30, 0x32, 0x20, 0xc4, 0x97, 0x51, 0x16, 0x7c, 0xa2, - 0x85, 0xa3, 0xe7, 0x88, 0x1f, 0x34, 0xe0, 0x05, 0xdd, 0xc8, 0xed, 0x57, 0x37, 0x06, 0x0e, 0xaa, - 0x1b, 0xf9, 0x87, 0xab, 0x1b, 0x6f, 0xa2, 0x61, 0xa8, 0xc9, 0xcf, 0xc8, 0xb4, 0xfb, 0xf2, 0x76, - 0x9e, 0xaf, 0x40, 0x23, 0xac, 0xdd, 0x3c, 0x2f, 0x13, 0x2c, 0x3c, 0x12, 0xab, 0x88, 0xda, 0xa1, - 0x43, 0xa8, 0xdd, 0xef, 0xa6, 0xd0, 0xc0, 0x1d, 0x6b, 0xc3, 0xb2, 0x37, 0x0f, 0xa7, 0x71, 0xcf, - 0xa2, 0x21, 0xce, 0x46, 0x98, 0xe3, 0xe1, 0xad, 0x6b, 0x87, 0x81, 0xeb, 0xc0, 0x49, 0x13, 0xa9, - 0xf0, 0xcb, 0x41, 0x21, 0x78, 0xf6, 0x90, 0x09, 0x93, 0x12, 0xf8, 0x85, 0x1a, 0x72, 0x1c, 0x75, - 0x91, 0x1c, 0x5f, 0x40, 0xd9, 0x32, 0x6d, 0xaa, 0x10, 0x95, 0x93, 0x36, 0x45, 0x03, 0xa8, 0xfa, - 0x2f, 0xd2, 0x68, 0x34, 0x72, 0xfc, 0xf4, 0x14, 0x1a, 0xe4, 0xc7, 0x3f, 0xa6, 0x1f, 0xd8, 0x1d, - 0x9e, 0x45, 0x04, 0x40, 0x2d, 0xcf, 0xfe, 0xac, 0x18, 0xf8, 0x93, 0x68, 0xc0, 0x76, 0x61, 0x69, - 0x82, 0x6f, 0x19, 0x0d, 0x87, 0xd0, 0x52, 0x8d, 0xb6, 0x9d, 0x0d, 0x0e, 0x4e, 0x22, 0x6a, 0xa4, - 0xed, 0xc2, 0xa7, 0xdd, 0x44, 0x83, 0xba, 0xeb, 0x12, 0xaf, 0xee, 0xe9, 0x6b, 0x62, 0xac, 0xf7, - 0x00, 0x28, 0x8e, 0x0e, 0x00, 0x2e, 0xeb, 0x6b, 0xf8, 0x35, 0x34, 0xd2, 0x70, 0x08, 0x2c, 0x5e, - 0x7a, 0x93, 0xb6, 0x52, 0x30, 0x2e, 0x25, 0x84, 0x78, 0xe2, 0x1f, 0x22, 0x2a, 0x06, 0xbe, 0x8b, - 0x46, 0xf8, 0xe7, 0x30, 0x9f, 0x64, 0x18, 0x68, 0xa3, 0xe1, 0x62, 0xc2, 0x44, 0xc2, 0xbc, 0x92, - 0xb9, 0x6b, 0xba, 0x48, 0x2e, 0xf2, 0x35, 0x04, 0x52, 0xf5, 0x6b, 0x29, 0x6a, 0xf0, 0x50, 0x00, - 0xe4, 0x48, 0xa5, 0xba, 0xd2, 0xda, 0xa7, 0xae, 0xb4, 0xc2, 0x6c, 0x66, 0x39, 0xb7, 0xc7, 0xec, - 0xa4, 0x71, 0x2c, 0x9e, 0x44, 0x39, 0x43, 0x3c, 0xfb, 0x39, 0x2b, 0x7f, 0x84, 0x5f, 0x8f, 0xc6, - 0xa9, 0xf0, 0x15, 0x94, 0xa5, 0x06, 0x6d, 0x74, 0xe3, 0x27, 0xae, 0x91, 0x1a, 0x50, 0xa8, 0xdf, - 0x96, 0x46, 0xc3, 0xc2, 0xd7, 0xdc, 0x38, 0xd4, 0xe7, 0xbc, 0xb4, 0xb7, 0x66, 0xfa, 0x6e, 0x0e, - 0xb0, 0x23, 0xf0, 0x9b, 0x7c, 0x33, 0x10, 0xc5, 0x9e, 0xae, 0x20, 0xb8, 0x60, 0x9e, 0xe7, 0x1f, - 0x9a, 0xdb, 0xfb, 0x26, 0x88, 0xd2, 0xbf, 0x9e, 0xcd, 0xa7, 0x0b, 0x99, 0xd7, 0xb3, 0xf9, 0x6c, - 0xa1, 0x5f, 0xfd, 0xa7, 0x6f, 0xa1, 0xfe, 0x25, 0x8b, 0x2c, 0xad, 0xe2, 0x67, 0x84, 0x5c, 0x9d, - 0xfc, 0xe3, 0xc7, 0x45, 0x96, 0x80, 0x98, 0xeb, 0xd3, 0x84, 0x8c, 0x9e, 0x37, 0xc5, 0xa4, 0x6d, - 0xbc, 0x17, 0xb1, 0x58, 0x86, 0x61, 0xe6, 0xfa, 0x34, 0x31, 0xb9, 0xdb, 0x4d, 0x31, 0x59, 0x16, - 0x17, 0x96, 0x54, 0x8a, 0x61, 0xfc, 0x52, 0xfc, 0x18, 0x62, 0x3e, 0x29, 0xa3, 0x54, 0xf4, 0x20, - 0x2f, 0x4e, 0x31, 0xd7, 0xa7, 0x25, 0x67, 0xa2, 0x1a, 0x16, 0xef, 0x2a, 0xa2, 0x67, 0x24, 0x22, - 0x6e, 0xae, 0x4f, 0x93, 0x68, 0xf1, 0x0b, 0x41, 0x46, 0x5f, 0xba, 0x40, 0x47, 0x9f, 0x43, 0x09, - 0xa8, 0xb9, 0x3e, 0x4d, 0xa4, 0x14, 0x2a, 0xad, 0x3a, 0x66, 0x90, 0x6e, 0x33, 0x5a, 0x29, 0xe0, - 0x84, 0x4a, 0xe1, 0x37, 0x7e, 0x05, 0x8d, 0x04, 0xef, 0xcc, 0xde, 0x21, 0x0d, 0x8f, 0xaf, 0x52, - 0x67, 0x22, 0x85, 0x19, 0x72, 0xae, 0x4f, 0x93, 0xa9, 0xf1, 0x15, 0x94, 0xd3, 0x88, 0x6b, 0xbe, - 0xeb, 0xef, 0xae, 0x46, 0x85, 0x63, 0x18, 0xf3, 0x5d, 0x2a, 0x25, 0x8e, 0xa7, 0xbd, 0x13, 0x6e, - 0xe7, 0xf8, 0x9a, 0x82, 0x23, 0xb5, 0xcc, 0x58, 0x06, 0xed, 0x1d, 0x61, 0x2f, 0xff, 0x5a, 0x34, - 0xdb, 0x3d, 0x6c, 0x85, 0x24, 0x37, 0x67, 0x11, 0x3b, 0xd7, 0xa7, 0x45, 0xb3, 0xe3, 0xbf, 0x20, - 0x65, 0x5a, 0xe7, 0x01, 0x0f, 0xa2, 0x52, 0xa5, 0x28, 0x41, 0xaa, 0x90, 0x93, 0xfd, 0xb5, 0x68, - 0xea, 0x6f, 0x1e, 0xde, 0xe0, 0x6c, 0x72, 0x82, 0x68, 0xa1, 0x6a, 0x3f, 0x55, 0xf8, 0x0b, 0x52, - 0x8a, 0x66, 0x65, 0x34, 0xb9, 0x6a, 0xdd, 0xd3, 0xc5, 0xaa, 0xd9, 0x90, 0x97, 0x92, 0x05, 0x43, - 0xc2, 0xa2, 0x78, 0x87, 0x02, 0x4e, 0xe8, 0x50, 0x96, 0x58, 0xf8, 0x05, 0x29, 0x29, 0x0d, 0xcf, - 0x48, 0x14, 0x54, 0x2a, 0xa0, 0x68, 0xa5, 0x62, 0xfa, 0x9a, 0x9b, 0x62, 0xae, 0x16, 0x65, 0x5c, - 0xee, 0xa0, 0x10, 0x43, 0x3b, 0x48, 0xc8, 0xe9, 0x52, 0x84, 0x3c, 0x10, 0x0a, 0x06, 0xf2, 0xa1, - 0xa0, 0x85, 0xd3, 0xd5, 0xb9, 0x3e, 0x0d, 0x32, 0x44, 0xa8, 0x2c, 0xc3, 0x88, 0x72, 0x0a, 0x28, - 0x86, 0x83, 0x54, 0xd8, 0x0f, 0x48, 0x63, 0xae, 0x4f, 0x63, 0xd9, 0x47, 0x9e, 0x11, 0x62, 0x79, - 0x2b, 0xa7, 0xe5, 0x29, 0x22, 0x40, 0xd0, 0x29, 0x22, 0x8c, 0xf8, 0x3d, 0x1b, 0x8f, 0x77, 0xad, - 0x9c, 0x91, 0x4f, 0x02, 0xa3, 0xf8, 0xb9, 0x3e, 0x2d, 0x1e, 0x23, 0xfb, 0x05, 0x29, 0x04, 0xb4, - 0x72, 0x36, 0xf2, 0x06, 0x31, 0x44, 0x51, 0x71, 0x89, 0xc1, 0xa2, 0x97, 0x12, 0x93, 0xb6, 0x29, - 0xe7, 0x80, 0xc1, 0x63, 0x01, 0x83, 0x38, 0xc9, 0x5c, 0x9f, 0x96, 0x98, 0xee, 0x6d, 0x3a, 0x16, - 0x88, 0x59, 0x51, 0xe4, 0xa3, 0xa4, 0x08, 0x7a, 0xae, 0x4f, 0x8b, 0x85, 0x6e, 0xbe, 0x29, 0x46, - 0x40, 0x56, 0xce, 0xcb, 0x9d, 0x18, 0x62, 0x68, 0x27, 0x0a, 0x91, 0x92, 0x6f, 0x8a, 0x51, 0x71, - 0x95, 0x89, 0x78, 0xa9, 0x70, 0xe6, 0x14, 0xa2, 0xe7, 0x6a, 0xc9, 0x81, 0x3e, 0x95, 0xc7, 0x78, - 0xaa, 0x05, 0x5e, 0x3e, 0x89, 0x66, 0xae, 0x4f, 0x4b, 0x0e, 0x12, 0xaa, 0x25, 0x47, 0xc8, 0x54, - 0x2e, 0xf4, 0xe2, 0x19, 0xb4, 0x2e, 0x39, 0xba, 0xa6, 0xde, 0x23, 0x5e, 0xa1, 0x72, 0x51, 0x0e, - 0x80, 0xd2, 0x95, 0x70, 0xae, 0x4f, 0xeb, 0x11, 0xf5, 0xf0, 0x4e, 0x97, 0xe0, 0x81, 0xca, 0x25, - 0x39, 0xd3, 0x4a, 0x22, 0xd1, 0x5c, 0x9f, 0xd6, 0x25, 0xf4, 0xe0, 0x9d, 0x2e, 0xb1, 0xe5, 0x94, - 0x62, 0x4f, 0xb6, 0x81, 0x3c, 0xba, 0x44, 0xa6, 0x5b, 0x4a, 0x0c, 0xcb, 0xa6, 0x3c, 0x2e, 0xab, - 0x6e, 0x02, 0x09, 0x55, 0xdd, 0xa4, 0x80, 0x6e, 0x4b, 0x89, 0x71, 0xc4, 0x94, 0x27, 0x7a, 0x30, - 0x0c, 0xda, 0x98, 0x18, 0x81, 0x6c, 0x29, 0x31, 0x90, 0x97, 0xa2, 0xca, 0x0c, 0x13, 0x48, 0x28, - 0xc3, 0xa4, 0x10, 0x60, 0x4b, 0x89, 0x91, 0xa7, 0x94, 0x27, 0x7b, 0x30, 0x0c, 0x5b, 0x98, 0x14, - 0xb3, 0xea, 0x05, 0x29, 0xf4, 0x93, 0xf2, 0x21, 0x79, 0xde, 0x10, 0x50, 0x74, 0xde, 0x10, 0x83, - 0x44, 0x4d, 0xc7, 0x82, 0x5b, 0x28, 0x1f, 0x96, 0x87, 0x79, 0x04, 0x4d, 0x87, 0x79, 0x34, 0x1c, - 0xc6, 0x74, 0xec, 0x91, 0xbf, 0x72, 0xb9, 0x1b, 0x13, 0x40, 0xcb, 0x4c, 0x58, 0x58, 0x80, 0x4a, - 0xc2, 0x2b, 0x73, 0xe5, 0x23, 0xf2, 0x35, 0x68, 0x8c, 0x60, 0xae, 0x4f, 0x4b, 0x78, 0x9b, 0xae, - 0x25, 0x3f, 0xa9, 0x52, 0xae, 0xc8, 0xc3, 0x36, 0x89, 0x86, 0x0e, 0xdb, 0xc4, 0xe7, 0x58, 0xf3, - 0x49, 0x2e, 0x0f, 0xca, 0x55, 0xd9, 0x30, 0x8b, 0x53, 0x50, 0xc3, 0x2c, 0xc1, 0x55, 0x42, 0x4b, - 0x7e, 0x24, 0xa4, 0x3c, 0xd5, 0xb3, 0x85, 0x40, 0x93, 0xd0, 0x42, 0xf6, 0x66, 0x26, 0xb4, 0x9d, - 0xee, 0xb4, 0x9b, 0xb6, 0x6e, 0x28, 0x1f, 0x4d, 0xb4, 0x9d, 0x18, 0x52, 0xb0, 0x9d, 0x18, 0x80, - 0xae, 0xf2, 0xa2, 0x4b, 0x80, 0x72, 0x4d, 0x5e, 0xe5, 0x45, 0x1c, 0x5d, 0xe5, 0x25, 0xf7, 0x81, - 0xe9, 0xd8, 0xf5, 0xb9, 0xf2, 0xb4, 0xac, 0x00, 0x11, 0x34, 0x55, 0x80, 0xe8, 0x85, 0xfb, 0xdb, - 0xdd, 0x2f, 0x9c, 0x95, 0x49, 0xe0, 0xf6, 0xb8, 0xcf, 0xad, 0x1b, 0xdd, 0x5c, 0x9f, 0xd6, 0xfd, - 0xd2, 0xba, 0x92, 0x70, 0x7f, 0xac, 0x5c, 0x97, 0x15, 0x2c, 0x46, 0x40, 0x15, 0x2c, 0x7e, 0xeb, - 0x5c, 0x49, 0xb8, 0x00, 0x56, 0x3e, 0xd6, 0x95, 0x55, 0xf0, 0xcd, 0x09, 0xd7, 0xc6, 0x37, 0xc5, - 0x1b, 0x5c, 0xe5, 0x19, 0x79, 0xb1, 0x0b, 0x31, 0x74, 0xb1, 0x13, 0x6e, 0x7a, 0x6f, 0x8a, 0x77, - 0x97, 0xca, 0x8d, 0x78, 0xa9, 0x70, 0x89, 0x14, 0xee, 0x38, 0xb5, 0xe4, 0x2b, 0x3f, 0xe5, 0x59, - 0x59, 0xeb, 0x92, 0x68, 0xa8, 0xd6, 0x25, 0x5e, 0x17, 0xce, 0xc6, 0x6f, 0xee, 0x94, 0x9b, 0xd1, - 0x3b, 0x50, 0x19, 0x4f, 0x2d, 0x9f, 0xd8, 0x6d, 0xdf, 0x6b, 0xd1, 0xf7, 0xbe, 0xca, 0x73, 0x91, - 0xfd, 0xa5, 0x84, 0xa5, 0xf6, 0x6d, 0xe4, 0x7d, 0xf0, 0x6b, 0xd1, 0x27, 0xb2, 0xca, 0xf3, 0xc9, - 0x1c, 0x02, 0x5d, 0x89, 0x3e, 0xa9, 0x7d, 0x2d, 0xfa, 0xaa, 0x54, 0x79, 0x21, 0x99, 0x43, 0x20, - 0xdd, 0xe8, 0x2b, 0xd4, 0x67, 0x84, 0x38, 0x57, 0xca, 0xc7, 0x65, 0xd3, 0x31, 0x40, 0x50, 0xd3, - 0x31, 0x8c, 0x86, 0xf5, 0x8c, 0x10, 0x1f, 0x4a, 0x79, 0x31, 0x56, 0x24, 0x68, 0xac, 0x10, 0x45, - 0xea, 0x19, 0x21, 0xae, 0x92, 0xf2, 0x52, 0xac, 0x48, 0xd0, 0x3a, 0x21, 0xfa, 0x92, 0xd1, 0xcb, - 0x35, 0x52, 0xf9, 0x04, 0xf0, 0x50, 0x77, 0xf7, 0x76, 0x9b, 0xeb, 0xd3, 0x7a, 0xb9, 0x58, 0xbe, - 0xdd, 0xfd, 0x1e, 0x54, 0x79, 0x59, 0x1e, 0xc2, 0xdd, 0xe8, 0xe8, 0x10, 0xee, 0x7a, 0x97, 0xfa, - 0x4a, 0xe4, 0x99, 0x84, 0xf2, 0x8a, 0x3c, 0xc5, 0x49, 0x48, 0x3a, 0xc5, 0x45, 0x1f, 0x55, 0x48, - 0xfe, 0xff, 0xca, 0x27, 0xe5, 0x29, 0x4e, 0xc4, 0xd1, 0x29, 0x4e, 0x7a, 0x2b, 0x30, 0x1d, 0x73, - 0x4b, 0x57, 0x5e, 0x95, 0xa7, 0xb8, 0x08, 0x9a, 0x4e, 0x71, 0x51, 0x47, 0xf6, 0x57, 0x22, 0xde, - 0xd9, 0xca, 0x6b, 0xc9, 0xed, 0x07, 0xa4, 0xd8, 0x7e, 0xe6, 0xcb, 0xad, 0x25, 0xbb, 0x19, 0x2b, - 0x25, 0x79, 0xfc, 0x26, 0xd1, 0xd0, 0xf1, 0x9b, 0xe8, 0xa2, 0xbc, 0x94, 0x98, 0xe7, 0x54, 0x99, - 0xea, 0xb1, 0x71, 0x08, 0x4d, 0x91, 0xa4, 0x0c, 0xa9, 0xe2, 0x1e, 0x99, 0x6d, 0x84, 0xa6, 0xbb, - 0xec, 0x91, 0xfd, 0x6d, 0x50, 0x84, 0x9e, 0xce, 0xae, 0xb1, 0x6b, 0x39, 0xa5, 0x2c, 0xcf, 0xae, - 0x31, 0x02, 0x3a, 0xbb, 0xc6, 0x2f, 0xf3, 0x66, 0x51, 0x81, 0x6b, 0x11, 0xbb, 0x6d, 0x34, 0xad, - 0x35, 0x65, 0x26, 0xe2, 0xe5, 0x17, 0xc1, 0xd3, 0xd9, 0x29, 0x0a, 0x83, 0xf5, 0x9a, 0xc1, 0xa6, - 0x9b, 0x66, 0x7b, 0xc5, 0xd6, 0x1d, 0xa3, 0x46, 0x2c, 0x43, 0x99, 0x8d, 0xac, 0xd7, 0x09, 0x34, - 0xb0, 0x5e, 0x27, 0xc0, 0xe1, 0x8d, 0x6b, 0x04, 0xae, 0x91, 0x06, 0x31, 0xef, 0x13, 0xe5, 0x16, - 0xb0, 0x2d, 0x76, 0x63, 0xcb, 0xc9, 0xe6, 0xfa, 0xb4, 0x6e, 0x1c, 0xa8, 0xad, 0xbe, 0xb0, 0x55, - 0x7b, 0x63, 0x3e, 0xf0, 0x6c, 0xaf, 0x3a, 0xa4, 0xad, 0x3b, 0x44, 0x99, 0x93, 0x6d, 0xf5, 0x44, - 0x22, 0x6a, 0xab, 0x27, 0x22, 0xe2, 0x6c, 0xfd, 0xb1, 0x50, 0xe9, 0xc5, 0x36, 0x1c, 0x11, 0xc9, - 0xa5, 0xe9, 0xec, 0x24, 0x23, 0xa8, 0x80, 0xe6, 0x6d, 0x6b, 0x0d, 0x4e, 0x2a, 0x5e, 0x97, 0x67, - 0xa7, 0xee, 0x94, 0x74, 0x76, 0xea, 0x8e, 0xa5, 0xaa, 0x2e, 0x63, 0xd9, 0x18, 0xbc, 0x2d, 0xab, - 0x7a, 0x02, 0x09, 0x55, 0xf5, 0x04, 0x70, 0x9c, 0xa1, 0x46, 0x5c, 0xe2, 0x29, 0xf3, 0xbd, 0x18, - 0x02, 0x49, 0x9c, 0x21, 0x80, 0xe3, 0x0c, 0x67, 0x89, 0xd7, 0x58, 0x57, 0x16, 0x7a, 0x31, 0x04, - 0x92, 0x38, 0x43, 0x00, 0xd3, 0xcd, 0xa6, 0x0c, 0x9e, 0xea, 0x34, 0x37, 0xfc, 0x3e, 0x5b, 0x94, - 0x37, 0x9b, 0x5d, 0x09, 0xe9, 0x66, 0xb3, 0x2b, 0x12, 0x7f, 0xcf, 0x9e, 0xaf, 0x8d, 0x95, 0x25, - 0xa8, 0x70, 0x32, 0xb4, 0x0b, 0xf6, 0x52, 0x6a, 0xae, 0x4f, 0xdb, 0xeb, 0xb5, 0xf4, 0x47, 0x83, - 0xdb, 0x1d, 0xa5, 0x0a, 0x55, 0x8d, 0x05, 0x67, 0x15, 0x0c, 0x3c, 0xd7, 0xa7, 0x05, 0xf7, 0x3f, - 0x2f, 0xa0, 0x21, 0xf8, 0xa8, 0x8a, 0x65, 0x7a, 0xe5, 0x29, 0xe5, 0x0d, 0x79, 0xcb, 0x24, 0xa0, - 0xe8, 0x96, 0x49, 0xf8, 0x49, 0x27, 0x71, 0xf8, 0xc9, 0xa6, 0x98, 0xf2, 0x94, 0xa2, 0xc9, 0x93, - 0xb8, 0x84, 0xa4, 0x93, 0xb8, 0x04, 0x08, 0xea, 0x2d, 0x3b, 0x76, 0xbb, 0x3c, 0xa5, 0xd4, 0x12, - 0xea, 0x65, 0xa8, 0xa0, 0x5e, 0xf6, 0x33, 0xa8, 0xb7, 0xb6, 0xde, 0xf1, 0xca, 0xf4, 0x1b, 0x97, - 0x13, 0xea, 0xf5, 0x91, 0x41, 0xbd, 0x3e, 0x80, 0x4e, 0x85, 0x00, 0xa8, 0x3a, 0x36, 0x9d, 0xb4, - 0x6f, 0x9b, 0xcd, 0xa6, 0x72, 0x47, 0x9e, 0x0a, 0xa3, 0x78, 0x3a, 0x15, 0x46, 0x61, 0xd4, 0xf4, - 0x64, 0xad, 0x22, 0x2b, 0x9d, 0x35, 0xe5, 0xae, 0x6c, 0x7a, 0x86, 0x18, 0x6a, 0x7a, 0x86, 0xbf, - 0x60, 0x77, 0x41, 0x7f, 0x69, 0x64, 0xd5, 0x21, 0xee, 0xba, 0x72, 0x2f, 0xb2, 0xbb, 0x10, 0x70, - 0xb0, 0xbb, 0x10, 0x7e, 0xe3, 0x35, 0xf4, 0x98, 0xb4, 0xd0, 0xf8, 0x3e, 0x73, 0x35, 0xa2, 0x3b, - 0x8d, 0x75, 0xe5, 0x53, 0xc0, 0xea, 0xc9, 0xc4, 0xa5, 0x4a, 0x26, 0x9d, 0xeb, 0xd3, 0x7a, 0x71, - 0x82, 0x6d, 0xf9, 0x1b, 0xf3, 0x2c, 0x18, 0x85, 0x56, 0x9d, 0xf6, 0x37, 0xa1, 0x6f, 0x46, 0xb6, - 0xe5, 0x71, 0x12, 0xd8, 0x96, 0xc7, 0xc1, 0xb8, 0x8d, 0x2e, 0x45, 0xb6, 0x6a, 0x0b, 0x7a, 0x93, - 0xee, 0x4b, 0x88, 0x51, 0xd5, 0x1b, 0x1b, 0xc4, 0x53, 0xde, 0x02, 0xde, 0x97, 0xbb, 0x6c, 0xf8, - 0x22, 0xd4, 0x73, 0x7d, 0xda, 0x2e, 0xfc, 0xb0, 0xca, 0x32, 0x69, 0x2a, 0x9f, 0x96, 0xcf, 0x37, - 0x29, 0x6c, 0xae, 0x4f, 0x63, 0x59, 0x36, 0xdf, 0x46, 0xca, 0x9d, 0xf6, 0x9a, 0xa3, 0x1b, 0x84, - 0x19, 0x5a, 0x60, 0xbb, 0x71, 0x03, 0xf4, 0x5b, 0x64, 0x2b, 0xad, 0x1b, 0x1d, 0xb5, 0xd2, 0xba, - 0xe1, 0xa8, 0xa2, 0x4a, 0x71, 0x17, 0x95, 0xcf, 0xc8, 0x8a, 0x2a, 0x21, 0xa9, 0xa2, 0xca, 0x51, - 0x1a, 0x3f, 0x85, 0xce, 0x06, 0xfb, 0x79, 0xbe, 0xfe, 0xb2, 0x4e, 0x53, 0xde, 0x06, 0x3e, 0x97, - 0x62, 0x97, 0x01, 0x12, 0xd5, 0x5c, 0x9f, 0xd6, 0xa5, 0x3c, 0x5d, 0x71, 0x63, 0x21, 0x85, 0xb9, - 0x79, 0xf1, 0xad, 0xf2, 0x8a, 0xdb, 0x85, 0x8c, 0xae, 0xb8, 0x5d, 0x50, 0x89, 0xcc, 0xb9, 0x50, - 0xf5, 0x5d, 0x98, 0x07, 0x32, 0xed, 0xc6, 0x21, 0x91, 0x39, 0xb7, 0xd4, 0x56, 0x76, 0x61, 0x1e, - 0x58, 0x6b, 0xdd, 0x38, 0xe0, 0x2b, 0x28, 0x57, 0xab, 0x2d, 0x68, 0x1d, 0x4b, 0x69, 0x44, 0xae, - 0xe5, 0x00, 0x3a, 0xd7, 0xa7, 0x71, 0x3c, 0x35, 0x83, 0x66, 0x9a, 0xba, 0xeb, 0x99, 0x0d, 0x17, - 0x46, 0x8c, 0x3f, 0x42, 0x0c, 0xd9, 0x0c, 0x4a, 0xa2, 0xa1, 0x66, 0x50, 0x12, 0x9c, 0xda, 0x8b, - 0xd3, 0xba, 0xeb, 0xea, 0x96, 0xe1, 0xe8, 0x53, 0xb0, 0x4c, 0x90, 0x88, 0xf3, 0x92, 0x84, 0xa5, - 0xf6, 0xa2, 0x0c, 0x81, 0xc3, 0x77, 0x1f, 0xe2, 0x9b, 0x39, 0xab, 0x91, 0xc3, 0xf7, 0x08, 0x1e, - 0x0e, 0xdf, 0x23, 0x30, 0xb0, 0x3b, 0x7d, 0x98, 0x46, 0xd6, 0x4c, 0xc8, 0x7b, 0xbd, 0x16, 0xb1, - 0x3b, 0xa3, 0x04, 0x60, 0x77, 0x46, 0x81, 0x52, 0x93, 0xfc, 0xe5, 0x76, 0xbd, 0x4b, 0x93, 0xc2, - 0x55, 0x36, 0x56, 0x86, 0xae, 0xdf, 0xe1, 0xe0, 0x28, 0x6f, 0x59, 0x7a, 0xcb, 0x2e, 0x4f, 0xf9, - 0x52, 0x37, 0xe5, 0xf5, 0xbb, 0x2b, 0x21, 0x5d, 0xbf, 0xbb, 0x22, 0xe9, 0xec, 0xea, 0x6f, 0xb4, - 0xd6, 0x75, 0x87, 0x18, 0x41, 0x36, 0x58, 0xb6, 0x35, 0x7c, 0x47, 0x9e, 0x5d, 0x7b, 0x90, 0xd2, - 0xd9, 0xb5, 0x07, 0x9a, 0x1a, 0x79, 0xc9, 0x68, 0x8d, 0xe8, 0x86, 0xb2, 0x21, 0x1b, 0x79, 0xdd, - 0x29, 0xa9, 0x91, 0xd7, 0x1d, 0xdb, 0xfd, 0x73, 0xee, 0x39, 0xa6, 0x47, 0x94, 0xe6, 0x5e, 0x3e, - 0x07, 0x48, 0xbb, 0x7f, 0x0e, 0xa0, 0xe9, 0x86, 0x30, 0xda, 0x21, 0x2d, 0x79, 0x43, 0x18, 0xef, - 0x86, 0x68, 0x09, 0x6a, 0xb1, 0x70, 0x1f, 0x36, 0xc5, 0x92, 0x2d, 0x16, 0x0e, 0xa6, 0x16, 0x4b, - 0xe8, 0xe5, 0x26, 0xf9, 0x4c, 0x29, 0xb6, 0xbc, 0x86, 0x8a, 0x38, 0xba, 0x86, 0x4a, 0xfe, 0x55, - 0x2f, 0x48, 0x0e, 0x0d, 0x4a, 0x5b, 0xb6, 0x3a, 0x04, 0x14, 0xb5, 0x3a, 0x44, 0xd7, 0x87, 0x69, - 0x34, 0x06, 0xb7, 0xe0, 0x5a, 0x27, 0xb8, 0xc7, 0xf9, 0xac, 0xfc, 0x99, 0x11, 0x34, 0xfd, 0xcc, - 0x08, 0x48, 0x62, 0xc2, 0xa7, 0x2d, 0xa7, 0x0b, 0x93, 0xf0, 0x7c, 0x30, 0x02, 0xc2, 0xf3, 0x08, - 0xd7, 0x4a, 0x0b, 0xf3, 0x15, 0xa3, 0x2a, 0x5e, 0x91, 0xb9, 0xf2, 0x09, 0x6c, 0x9c, 0x62, 0xae, - 0x4f, 0x4b, 0x28, 0x87, 0xdf, 0x41, 0x17, 0x38, 0x94, 0x3b, 0x28, 0x43, 0xbe, 0x2f, 0x23, 0x58, - 0x10, 0x3c, 0xe0, 0xfb, 0xa1, 0x08, 0xdf, 0x44, 0xda, 0xb9, 0x3e, 0xad, 0x27, 0xaf, 0xee, 0x75, - 0xf1, 0xf5, 0xa1, 0xb3, 0x97, 0xba, 0x82, 0x45, 0xa2, 0x27, 0xaf, 0xee, 0x75, 0x71, 0xb9, 0xdf, - 0xdf, 0x4b, 0x5d, 0x41, 0x27, 0xf4, 0xe4, 0x85, 0x5d, 0x54, 0xec, 0x85, 0x2f, 0x35, 0x9b, 0xca, - 0x26, 0x54, 0xf7, 0x91, 0xbd, 0x54, 0x57, 0x02, 0x83, 0x73, 0x37, 0x8e, 0x74, 0x96, 0x5e, 0x6a, - 0x13, 0xab, 0x26, 0x2d, 0x40, 0x0f, 0xe4, 0x59, 0x3a, 0x46, 0x40, 0x67, 0xe9, 0x18, 0x90, 0x0e, - 0x28, 0xd1, 0x2f, 0x46, 0xd9, 0x92, 0x07, 0x94, 0x88, 0xa3, 0x03, 0x4a, 0xf2, 0xa1, 0x59, 0x42, - 0xa7, 0x96, 0x36, 0x3c, 0xdd, 0xb7, 0x20, 0x5d, 0xde, 0x95, 0xef, 0x46, 0x2e, 0x99, 0xe2, 0x24, - 0x70, 0xc9, 0x14, 0x07, 0xd3, 0x31, 0x42, 0xc1, 0xb5, 0x2d, 0xab, 0x31, 0xab, 0x9b, 0xcd, 0x8e, - 0x43, 0x94, 0xff, 0x4f, 0x1e, 0x23, 0x11, 0x34, 0x1d, 0x23, 0x11, 0x10, 0x5d, 0xa0, 0x29, 0xa8, - 0xe4, 0xba, 0xe6, 0x9a, 0xc5, 0xf7, 0x95, 0x9d, 0xa6, 0xa7, 0xfc, 0xff, 0xf2, 0x02, 0x9d, 0x44, - 0x43, 0x17, 0xe8, 0x24, 0x38, 0x9c, 0x3a, 0x25, 0xe4, 0xc2, 0x53, 0xfe, 0x5c, 0xe4, 0xd4, 0x29, - 0x81, 0x06, 0x4e, 0x9d, 0x92, 0xf2, 0xe8, 0xcd, 0xa2, 0x02, 0xb3, 0xc9, 0xe6, 0xcd, 0xe0, 0xae, - 0xfa, 0xcf, 0xcb, 0xeb, 0x63, 0x14, 0x4f, 0xd7, 0xc7, 0x28, 0x4c, 0xe6, 0xc3, 0xbb, 0xe0, 0x2f, - 0x74, 0xe3, 0x13, 0xc8, 0x3f, 0x56, 0x06, 0xdf, 0x12, 0xf9, 0xf0, 0x91, 0xf2, 0x6d, 0xa9, 0x6e, - 0x8c, 0x82, 0xe1, 0x11, 0x2b, 0x24, 0x33, 0xd2, 0xc8, 0x7d, 0x93, 0x6c, 0x2a, 0x9f, 0xeb, 0xca, - 0x88, 0x11, 0xc8, 0x8c, 0x18, 0x0c, 0xbf, 0x89, 0xce, 0x86, 0xb0, 0x05, 0xd2, 0x5a, 0x09, 0x66, - 0xa6, 0x6f, 0x4f, 0xc9, 0x66, 0x70, 0x32, 0x19, 0x35, 0x83, 0x93, 0x31, 0x49, 0xac, 0xb9, 0xe8, - 0xfe, 0xe2, 0x2e, 0xac, 0x03, 0x09, 0x76, 0x61, 0x90, 0xc4, 0x9a, 0x4b, 0xf3, 0x3b, 0x76, 0x61, - 0x1d, 0xc8, 0xb4, 0x0b, 0x03, 0xfc, 0xf9, 0x14, 0xba, 0x9c, 0x8c, 0x2a, 0x35, 0x9b, 0xb3, 0xb6, - 0x13, 0xe2, 0x94, 0xef, 0x4c, 0xc9, 0x07, 0x0d, 0x7b, 0x2b, 0x36, 0xd7, 0xa7, 0xed, 0xb1, 0x02, - 0xfc, 0x49, 0x34, 0x52, 0xea, 0x18, 0xa6, 0x07, 0x17, 0x6f, 0xd4, 0x70, 0xfe, 0xae, 0x54, 0x64, - 0x8b, 0x23, 0x62, 0x61, 0x8b, 0x23, 0x02, 0xf0, 0xeb, 0x68, 0xbc, 0x46, 0x1a, 0x1d, 0xc7, 0xf4, - 0xb6, 0x34, 0xc8, 0x73, 0x48, 0x79, 0x7c, 0x77, 0x4a, 0x9e, 0xc4, 0x62, 0x14, 0x74, 0x12, 0x8b, - 0x01, 0xf1, 0xdd, 0x2e, 0xd9, 0xf0, 0x94, 0xef, 0x49, 0xf5, 0xbc, 0x96, 0x0f, 0xfa, 0xb2, 0x4b, - 0x32, 0xbd, 0x6a, 0x62, 0x76, 0x31, 0xe5, 0xf3, 0xa9, 0x1e, 0xd7, 0xe8, 0xc2, 0x0c, 0x97, 0x90, - 0x98, 0xac, 0x9a, 0x98, 0x3f, 0x4a, 0xf9, 0xde, 0x54, 0x8f, 0x6b, 0xef, 0x90, 0x63, 0x52, 0xea, - 0xa9, 0xe7, 0xc4, 0x84, 0xd2, 0xca, 0x5f, 0x4a, 0xc5, 0x5d, 0x45, 0x82, 0xf2, 0x62, 0xe6, 0xe9, - 0xe7, 0x98, 0x6b, 0x1e, 0x2f, 0xf6, 0x85, 0x54, 0xdc, 0x37, 0x2f, 0x2c, 0x16, 0xfe, 0xc2, 0x04, - 0x4d, 0xcc, 0x3c, 0xf0, 0x88, 0x63, 0xe9, 0x4d, 0xe8, 0xce, 0x9a, 0x67, 0x3b, 0xfa, 0x1a, 0x99, - 0xb1, 0xf4, 0x95, 0x26, 0x51, 0xbe, 0x2f, 0x25, 0x5b, 0xb0, 0xdd, 0x49, 0xa9, 0x05, 0xdb, 0x1d, - 0x8b, 0xd7, 0xd1, 0x63, 0x49, 0xd8, 0xb2, 0xe9, 0x42, 0x3d, 0x5f, 0x4c, 0xc9, 0x26, 0x6c, 0x0f, - 0x5a, 0x6a, 0xc2, 0xf6, 0x40, 0xe3, 0x1b, 0x42, 0xb6, 0x65, 0xe5, 0x2f, 0x47, 0x9c, 0x21, 0x03, - 0xcc, 0x5c, 0x9f, 0x26, 0x24, 0x65, 0xbe, 0x21, 0x64, 0x05, 0x56, 0xbe, 0x14, 0x2f, 0x13, 0x5e, - 0x3e, 0x85, 0xc9, 0x83, 0x6f, 0x08, 0xf9, 0x90, 0x95, 0xbf, 0x12, 0x2f, 0x13, 0xde, 0x71, 0x85, - 0x69, 0x93, 0xdf, 0x44, 0x67, 0x59, 0x8d, 0x0b, 0xb3, 0x25, 0x6a, 0xb7, 0x4d, 0xaf, 0xeb, 0xcd, - 0x26, 0xb1, 0xd6, 0x88, 0xf2, 0xe5, 0xc8, 0x4c, 0x92, 0x4c, 0x46, 0x67, 0x92, 0x64, 0x0c, 0xfe, - 0x16, 0x74, 0xee, 0xae, 0xde, 0x34, 0x8d, 0x10, 0xe7, 0xa7, 0x24, 0x52, 0xbe, 0x3f, 0x25, 0xef, - 0xa6, 0xbb, 0xd0, 0xd1, 0xdd, 0x74, 0x17, 0x14, 0x5e, 0x40, 0x18, 0x96, 0xd1, 0x60, 0xb6, 0xa0, - 0xeb, 0xb3, 0xf2, 0x57, 0x53, 0xb2, 0x9d, 0x1a, 0x27, 0xa1, 0x76, 0x6a, 0x1c, 0x8a, 0xeb, 0xdd, - 0xa3, 0x4e, 0x2a, 0x3f, 0x90, 0x92, 0x4f, 0x6b, 0xba, 0x11, 0xce, 0xf5, 0x69, 0xdd, 0x43, 0x57, - 0xde, 0x42, 0x85, 0x5a, 0xb5, 0x32, 0x3b, 0x3b, 0x53, 0xbb, 0x5b, 0x29, 0x57, 0x5c, 0xb7, 0x43, - 0x0c, 0xe5, 0x07, 0x23, 0x2b, 0x56, 0x94, 0x80, 0xae, 0x58, 0x51, 0x18, 0xae, 0xa1, 0xd3, 0x54, - 0x10, 0x55, 0x87, 0xac, 0x12, 0x87, 0x58, 0x0d, 0x7f, 0x58, 0xfe, 0x70, 0x4a, 0x36, 0x14, 0x92, - 0x88, 0xa8, 0xa1, 0x90, 0x04, 0xc7, 0x1b, 0xe8, 0x42, 0xf4, 0x30, 0x67, 0xda, 0xb6, 0x56, 0xcd, - 0x35, 0xce, 0xfc, 0x47, 0x52, 0x11, 0x7b, 0xb6, 0x07, 0x31, 0xd8, 0xb3, 0x3d, 0xf0, 0xd8, 0x42, - 0x17, 0xf9, 0xc9, 0x08, 0xf7, 0x99, 0x8c, 0xd6, 0xf6, 0xd7, 0x58, 0x6d, 0x1f, 0x0e, 0x7d, 0xfa, - 0x7a, 0x50, 0xcf, 0xf5, 0x69, 0xbd, 0xd9, 0x51, 0x55, 0x89, 0x87, 0x47, 0x54, 0x7e, 0x34, 0x95, - 0xec, 0x54, 0x22, 0x79, 0x1a, 0x27, 0xc5, 0x55, 0x7c, 0xb3, 0x5b, 0x70, 0x3f, 0xe5, 0xc7, 0x22, - 0x43, 0x26, 0x99, 0x8c, 0x0e, 0x99, 0x64, 0xcc, 0xd4, 0x00, 0xea, 0x07, 0xbb, 0x57, 0xfd, 0xf1, - 0x14, 0x1a, 0xae, 0x79, 0x0e, 0xd1, 0x5b, 0xfc, 0x19, 0xcd, 0x04, 0xca, 0x33, 0x07, 0x92, 0x4a, - 0x99, 0xbf, 0xba, 0x0b, 0x7e, 0xe3, 0xcb, 0x68, 0x74, 0x5e, 0x77, 0x3d, 0x28, 0x59, 0xb1, 0x0c, - 0xf2, 0x00, 0x9c, 0xa7, 0x33, 0x5a, 0x04, 0x8a, 0xe7, 0x19, 0x1d, 0x2b, 0x07, 0xef, 0x17, 0x33, - 0xbb, 0xbe, 0x1e, 0xc9, 0xbf, 0xb7, 0x5d, 0xec, 0x83, 0xc7, 0x22, 0x91, 0xb2, 0xea, 0xd7, 0x52, - 0x28, 0xe6, 0xda, 0x72, 0xf0, 0xa7, 0x1e, 0x4b, 0x68, 0x2c, 0xf2, 0x66, 0x96, 0x7b, 0x80, 0xef, - 0xf1, 0x49, 0x6d, 0xb4, 0x34, 0xfe, 0x48, 0xe0, 0x79, 0x7c, 0x47, 0x9b, 0xe7, 0x2f, 0x83, 0x06, - 0x76, 0xb6, 0x8b, 0x99, 0x8e, 0xd3, 0xd4, 0x04, 0x14, 0xf7, 0x5c, 0xff, 0xf9, 0x42, 0xf8, 0x20, - 0x10, 0x5f, 0xe6, 0xef, 0x81, 0x53, 0xe1, 0x7b, 0xa2, 0x48, 0x6e, 0x00, 0xf6, 0xfe, 0xf7, 0x93, - 0x68, 0xb8, 0xd2, 0x6a, 0x13, 0xc7, 0xb5, 0x2d, 0xdd, 0xb3, 0xfd, 0x1c, 0x64, 0xf0, 0xd6, 0xc4, - 0x14, 0xe0, 0xe2, 0xfb, 0x07, 0x91, 0x1e, 0x5f, 0xf5, 0x03, 0x49, 0x66, 0xe0, 0x29, 0xe6, 0xa9, - 0x84, 0x74, 0xd1, 0x7e, 0xd2, 0xe7, 0xab, 0xa8, 0xff, 0x8e, 0xab, 0x83, 0x8f, 0x7a, 0x40, 0xda, - 0xa1, 0x00, 0x91, 0x14, 0x28, 0xf0, 0x35, 0x94, 0x83, 0x3d, 0xbd, 0x0b, 0x01, 0x62, 0xf9, 0x2b, - 0xa7, 0x26, 0x40, 0xc4, 0x37, 0x25, 0x8c, 0x06, 0xdf, 0x46, 0x85, 0xf0, 0xc0, 0x12, 0xb2, 0xe6, - 0xf9, 0x21, 0xa1, 0x20, 0x4e, 0xff, 0x46, 0x80, 0x63, 0xe9, 0xf6, 0x44, 0x16, 0xb1, 0x82, 0x78, - 0x0e, 0x8d, 0x85, 0x30, 0x2a, 0x22, 0x3f, 0x14, 0x1d, 0xe4, 0xa9, 0x10, 0x78, 0x51, 0x71, 0x8a, - 0xac, 0xa2, 0xc5, 0x70, 0x05, 0x0d, 0xf8, 0x4f, 0x9c, 0xf2, 0xbb, 0x2a, 0xe9, 0x29, 0xfe, 0xc4, - 0x69, 0x40, 0x7c, 0xdc, 0xe4, 0x97, 0xc7, 0xb3, 0x68, 0x54, 0xb3, 0x3b, 0x1e, 0x59, 0xb6, 0xf9, - 0x34, 0xc1, 0x63, 0x15, 0x41, 0x9b, 0x1c, 0x8a, 0xa9, 0x7b, 0xb6, 0x9f, 0xe6, 0x40, 0x0c, 0xb7, - 0x2f, 0x97, 0xc2, 0x8b, 0x68, 0x3c, 0x76, 0xb4, 0x2b, 0x26, 0x1f, 0x10, 0x3e, 0x2f, 0xce, 0x2c, - 0x5e, 0x14, 0x7f, 0x57, 0x0a, 0xe5, 0x96, 0x1d, 0xdd, 0xf4, 0x5c, 0xee, 0xde, 0x7e, 0x66, 0x72, - 0xd3, 0xd1, 0xdb, 0x54, 0x3f, 0x26, 0xe1, 0xad, 0xed, 0x5d, 0xbd, 0xd9, 0x21, 0xee, 0xd4, 0x3d, - 0xfa, 0x75, 0xff, 0x6e, 0xbb, 0xf8, 0x89, 0x7d, 0xa4, 0xf1, 0xbe, 0x1e, 0x70, 0x62, 0x35, 0x50, - 0x15, 0xf0, 0xe0, 0x2f, 0x51, 0x05, 0x18, 0x0e, 0x2f, 0x52, 0xf3, 0x0e, 0x3e, 0xb5, 0xd4, 0x6e, - 0x73, 0x5f, 0x79, 0xc1, 0xba, 0xf3, 0x31, 0x4c, 0xb1, 0x03, 0x81, 0xe9, 0x6d, 0x31, 0xf7, 0xa2, - 0xc0, 0x81, 0x6a, 0xc1, 0x32, 0x6f, 0x91, 0x2f, 0xa6, 0x91, 0x50, 0xe2, 0x7e, 0x63, 0x13, 0x84, - 0x14, 0x2d, 0x86, 0x57, 0xd0, 0x18, 0xe7, 0x1b, 0x04, 0x0f, 0x1a, 0x95, 0x67, 0x85, 0x08, 0x9a, - 0x29, 0x6d, 0xd0, 0x46, 0x83, 0x83, 0xc5, 0x3a, 0x22, 0x25, 0xf0, 0x54, 0x18, 0x37, 0x1b, 0x12, - 0x3d, 0x2a, 0x63, 0xa0, 0xb1, 0x17, 0x76, 0xb6, 0x8b, 0x8a, 0x5f, 0x9e, 0xe5, 0x87, 0x4c, 0xca, - 0x02, 0x01, 0x45, 0x44, 0x1e, 0x4c, 0xeb, 0x0b, 0x09, 0x3c, 0xa2, 0x3a, 0x2f, 0x17, 0xc1, 0xd3, - 0x68, 0x24, 0x70, 0xd5, 0xbb, 0x73, 0xa7, 0x52, 0x06, 0x67, 0x7c, 0x9e, 0xd1, 0x30, 0x12, 0x97, - 0x48, 0x64, 0x22, 0x95, 0xc1, 0xcf, 0xa2, 0x3c, 0x73, 0x76, 0xaf, 0x30, 0xef, 0x7c, 0xff, 0x49, - 0x34, 0xc0, 0xea, 0xa6, 0xd8, 0x63, 0x01, 0x21, 0x7e, 0x05, 0x0d, 0x95, 0xee, 0xd5, 0xe8, 0x3c, - 0x53, 0xd2, 0x16, 0x5d, 0xe5, 0x54, 0x18, 0x10, 0x0e, 0x12, 0x81, 0xd8, 0x4d, 0x52, 0xd7, 0x1d, - 0x69, 0xf2, 0x10, 0xe9, 0xf1, 0x0c, 0x1a, 0x95, 0x6e, 0xfb, 0x5c, 0xe5, 0x34, 0x70, 0x60, 0xb9, - 0x18, 0x01, 0x53, 0xe7, 0xe9, 0x40, 0xa5, 0x6c, 0x27, 0x72, 0x21, 0xaa, 0x35, 0xd4, 0x60, 0x6e, - 0x36, 0xed, 0x4d, 0x8d, 0x98, 0xd4, 0xd6, 0x01, 0xd7, 0xfe, 0x3c, 0xd3, 0x1a, 0x83, 0xa3, 0xea, - 0x0e, 0xc3, 0x49, 0xb9, 0x68, 0xe4, 0x62, 0xf8, 0x1d, 0x84, 0x21, 0x1c, 0x17, 0x31, 0xfc, 0xc3, - 0x9f, 0x4a, 0xd9, 0x55, 0xce, 0x42, 0xcc, 0x01, 0x1c, 0x8d, 0x18, 0x52, 0x29, 0x4f, 0x5d, 0xe6, - 0xd3, 0xc7, 0x25, 0x9d, 0x95, 0xaa, 0x07, 0xa9, 0x38, 0x4d, 0x43, 0x6c, 0x71, 0x02, 0x57, 0xbc, - 0x89, 0xce, 0x55, 0x1d, 0x72, 0xdf, 0xb4, 0x3b, 0xae, 0xbf, 0x7c, 0xf8, 0xf3, 0xd6, 0xb9, 0x5d, - 0xe7, 0xad, 0x27, 0x78, 0xc5, 0x67, 0xda, 0x0e, 0xb9, 0x5f, 0xf7, 0x5f, 0x9a, 0x4b, 0x4f, 0x34, - 0xbb, 0x71, 0xa7, 0xe2, 0x2a, 0xbd, 0xdb, 0x71, 0x08, 0x87, 0x9b, 0xc4, 0x55, 0x94, 0x70, 0xaa, - 0xd5, 0x29, 0xca, 0xe7, 0x68, 0x4a, 0xaa, 0x1b, 0x2d, 0x86, 0x35, 0x84, 0x6f, 0x4d, 0xfb, 0x07, - 0x81, 0xa5, 0x06, 0x8b, 0x4b, 0xad, 0x9c, 0x07, 0x66, 0x2a, 0x15, 0xcb, 0x5a, 0x23, 0x88, 0x3a, - 0x51, 0xd7, 0x39, 0x5e, 0x14, 0x4b, 0xbc, 0x34, 0x9e, 0x47, 0x85, 0xaa, 0x03, 0x36, 0xcd, 0x6d, - 0xb2, 0x55, 0xb5, 0x9b, 0x66, 0x63, 0x0b, 0x5e, 0x18, 0xf0, 0xa9, 0xb2, 0xcd, 0x70, 0xf5, 0x0d, - 0xb2, 0x55, 0x6f, 0x03, 0x56, 0x5c, 0x56, 0xa2, 0x25, 0xc5, 0x57, 0xe0, 0x8f, 0xed, 0xed, 0x15, - 0x38, 0x41, 0x05, 0x7e, 0x8c, 0xf8, 0xc0, 0x23, 0x16, 0x5d, 0xea, 0x5d, 0xfe, 0x9a, 0x40, 0x89, - 0x1c, 0x3b, 0x06, 0x78, 0x9e, 0x97, 0x86, 0x8d, 0x32, 0x12, 0x80, 0xc5, 0x86, 0x45, 0x8b, 0xa8, - 0x5f, 0xcc, 0x88, 0x53, 0x27, 0xbe, 0x80, 0xb2, 0x42, 0x10, 0x32, 0x78, 0x3c, 0x0a, 0x01, 0x1b, - 0xb2, 0xfc, 0x65, 0xfa, 0x20, 0x37, 0x3b, 0x82, 0xa0, 0x63, 0x10, 0xa1, 0xd5, 0x8f, 0x0c, 0x61, - 0x1a, 0x5a, 0x48, 0x00, 0xd1, 0x31, 0xc3, 0xf4, 0x7d, 0x19, 0x21, 0x3a, 0x66, 0x98, 0xbe, 0x4f, - 0x4a, 0xde, 0x77, 0x03, 0x0d, 0xf9, 0x66, 0x70, 0xf8, 0x78, 0x1a, 0xa2, 0x3b, 0xf8, 0x19, 0x7c, - 0x58, 0xf0, 0x08, 0x81, 0x08, 0xbf, 0x04, 0x39, 0xac, 0xf8, 0x48, 0xe6, 0x46, 0x12, 0xcc, 0xf2, - 0xe2, 0xc0, 0x8f, 0x24, 0xb1, 0xe2, 0xd4, 0x74, 0xce, 0x13, 0x35, 0xc9, 0x8f, 0x07, 0x0c, 0x73, - 0x9e, 0xa4, 0x7e, 0x5b, 0x52, 0x02, 0x56, 0xb1, 0x08, 0x5e, 0x42, 0xe3, 0x31, 0xe5, 0xe1, 0x4f, - 0xad, 0x21, 0xf3, 0x40, 0x82, 0xe6, 0x89, 0x6b, 0x6a, 0xac, 0xac, 0xfa, 0xed, 0xe9, 0xd8, 0x8a, - 0x41, 0x05, 0xc3, 0xa9, 0x84, 0xce, 0x01, 0xc1, 0xf8, 0xac, 0x99, 0x60, 0x04, 0x22, 0x7c, 0x05, - 0xe5, 0x23, 0x69, 0xac, 0x20, 0x18, 0x44, 0x90, 0xc3, 0x2a, 0xc0, 0xe2, 0x1b, 0x42, 0x84, 0x6a, - 0x21, 0x44, 0x81, 0x1f, 0xa1, 0x5a, 0x9c, 0x70, 0x83, 0x58, 0xd5, 0x37, 0x22, 0xc1, 0xf0, 0xfc, - 0x6c, 0x43, 0xf1, 0xd5, 0x2a, 0x0c, 0xf5, 0x19, 0xd8, 0x8a, 0xfd, 0xbb, 0xd9, 0x8a, 0xea, 0xaf, - 0xa5, 0xe2, 0xda, 0x8f, 0x6f, 0xc6, 0xdf, 0x29, 0xb3, 0x44, 0x43, 0x3e, 0x50, 0xac, 0x35, 0x78, - 0xb1, 0x2c, 0xbd, 0x38, 0x4e, 0x1f, 0xf8, 0xc5, 0x71, 0x66, 0x9f, 0x2f, 0x8e, 0xd5, 0xff, 0x9d, - 0xed, 0xe9, 0x8c, 0x72, 0x24, 0xd1, 0x7e, 0x5e, 0xa4, 0xfb, 0x1d, 0x5a, 0x7b, 0xc9, 0x8d, 0x59, - 0xed, 0xec, 0xae, 0xbd, 0xae, 0xb3, 0x51, 0xe3, 0x6a, 0x32, 0xa5, 0x98, 0xf6, 0x19, 0x5e, 0xb2, - 0x67, 0x13, 0xd2, 0x3e, 0x47, 0x73, 0x45, 0x89, 0x05, 0xf0, 0x73, 0x68, 0x30, 0x4c, 0x60, 0xdd, - 0x2f, 0xc4, 0x45, 0x48, 0xc8, 0x5b, 0x1d, 0x52, 0xe2, 0xcf, 0xa0, 0x9c, 0x94, 0xac, 0xec, 0xfa, - 0x1e, 0xbc, 0x77, 0x26, 0xc5, 0x68, 0x3b, 0x6c, 0xef, 0x10, 0x4d, 0x54, 0xc6, 0x99, 0xe2, 0x65, - 0x74, 0xaa, 0xea, 0x10, 0x03, 0xfc, 0xc4, 0x66, 0x1e, 0xb4, 0x1d, 0x1e, 0x0b, 0x89, 0x0d, 0x60, - 0x58, 0x3a, 0xda, 0x3e, 0x9a, 0x2e, 0x6a, 0x1c, 0x2f, 0x30, 0x4a, 0x2a, 0x4e, 0xed, 0x09, 0xd6, - 0x92, 0xdb, 0x64, 0x6b, 0xd3, 0x76, 0x0c, 0x16, 0x2e, 0x88, 0xdb, 0x13, 0x5c, 0xd0, 0x1b, 0x1c, - 0x25, 0xda, 0x13, 0x72, 0xa1, 0x89, 0x17, 0xd1, 0xd0, 0x41, 0x23, 0xd6, 0xfc, 0x5c, 0xba, 0x8b, - 0x5b, 0xe7, 0xa3, 0x1b, 0x69, 0x38, 0x88, 0xfa, 0xde, 0xdf, 0x25, 0xea, 0xfb, 0x37, 0xd2, 0x5d, - 0x7c, 0x56, 0x1f, 0xe9, 0xe8, 0xcc, 0x81, 0x30, 0xe4, 0xe8, 0xcc, 0x61, 0x60, 0x6c, 0xd3, 0xd0, - 0x44, 0xa2, 0x48, 0x1c, 0xf7, 0xdc, 0xae, 0x71, 0xdc, 0x7f, 0x32, 0xd3, 0xcb, 0xa7, 0xf7, 0x44, - 0xf6, 0xfb, 0x91, 0xfd, 0x0d, 0x34, 0x14, 0x48, 0x96, 0x67, 0x7c, 0x1d, 0x09, 0xe2, 0x63, 0x31, - 0x30, 0x94, 0x11, 0x88, 0xf0, 0x55, 0xd6, 0xd6, 0x9a, 0xf9, 0x2e, 0x8b, 0x11, 0x33, 0xc2, 0xa3, - 0x7f, 0xe8, 0x9e, 0x5e, 0x77, 0xcd, 0x77, 0x89, 0x16, 0xa0, 0xd5, 0x7f, 0x94, 0x4e, 0x74, 0x8c, - 0x3e, 0xe9, 0xa3, 0x7d, 0xf4, 0x51, 0x82, 0x10, 0x99, 0x4b, 0xf7, 0x89, 0x10, 0xf7, 0x21, 0xc4, - 0x3f, 0x4a, 0x27, 0x3a, 0xc0, 0x9f, 0x08, 0x71, 0x3f, 0xb3, 0xc5, 0x35, 0x34, 0xa8, 0xd9, 0x9b, - 0x2e, 0x24, 0x6d, 0xe2, 0x73, 0x05, 0x4c, 0xd4, 0x8e, 0xbd, 0xe9, 0xb2, 0x84, 0x56, 0x5a, 0x48, - 0xa0, 0xfe, 0x71, 0xba, 0xc7, 0x13, 0x81, 0x13, 0xc1, 0x7f, 0x33, 0x97, 0xc8, 0x5f, 0x4c, 0x4b, - 0x4f, 0x10, 0x1e, 0xe9, 0x34, 0x27, 0xb5, 0xc6, 0x3a, 0x69, 0xe9, 0xd1, 0x34, 0x27, 0x2e, 0x40, - 0x79, 0x94, 0xf4, 0x90, 0x44, 0xfd, 0x4a, 0x3a, 0xf2, 0x06, 0xe3, 0x44, 0x76, 0x7b, 0x96, 0x5d, - 0xa0, 0x75, 0xfc, 0x59, 0xc9, 0x89, 0xe4, 0xf6, 0x2a, 0xb9, 0xef, 0x49, 0x47, 0x5e, 0xe0, 0x3c, - 0xba, 0x19, 0x0f, 0xbe, 0x92, 0x8e, 0xbf, 0x26, 0x7a, 0x74, 0x35, 0xe9, 0x1a, 0x1a, 0xe4, 0x72, - 0x08, 0x96, 0x0a, 0x36, 0xef, 0x33, 0x20, 0x1c, 0xa0, 0x06, 0x04, 0xea, 0x77, 0xa6, 0x91, 0xfc, - 0x32, 0xea, 0x11, 0xd5, 0xa1, 0x5f, 0x4c, 0xcb, 0x6f, 0xc2, 0x1e, 0x5d, 0xfd, 0x99, 0x44, 0xa8, - 0xd6, 0x59, 0x69, 0xf0, 0x90, 0x62, 0xfd, 0xc2, 0x09, 0x7c, 0x00, 0xd5, 0x04, 0x0a, 0xf5, 0xff, - 0xa4, 0x13, 0x1f, 0xaa, 0x3d, 0xba, 0x02, 0x7c, 0x16, 0x4e, 0xc5, 0x1b, 0x56, 0x38, 0x91, 0xc3, - 0x21, 0x24, 0x1d, 0x7f, 0xb1, 0xe0, 0xac, 0x3e, 0x21, 0xfe, 0x78, 0x82, 0xb9, 0x06, 0x71, 0x54, - 0x13, 0xb3, 0x09, 0x8b, 0x86, 0xdb, 0x3f, 0x4f, 0xef, 0xf6, 0xae, 0xef, 0x51, 0x5e, 0x55, 0x07, - 0xaa, 0xfa, 0x16, 0xc4, 0x9f, 0xa1, 0x3d, 0x31, 0xcc, 0x42, 0x87, 0xb6, 0x19, 0x48, 0xbc, 0x11, - 0xe3, 0x54, 0xea, 0x1f, 0xf6, 0x27, 0x3f, 0x2a, 0x7b, 0x74, 0x45, 0x78, 0x01, 0x65, 0xab, 0xba, - 0xb7, 0xce, 0x35, 0x19, 0x6e, 0xeb, 0xda, 0xba, 0xb7, 0xae, 0x01, 0x14, 0x5f, 0x45, 0x79, 0x4d, - 0xdf, 0x14, 0x33, 0x5d, 0xc2, 0xc1, 0x8e, 0xa3, 0x6f, 0xf2, 0x54, 0xda, 0x01, 0x1a, 0xab, 0x41, - 0x58, 0x61, 0x76, 0xf2, 0x0d, 0x31, 0x39, 0x59, 0x58, 0xe1, 0x20, 0x98, 0xf0, 0x05, 0x94, 0x9d, - 0xb2, 0x8d, 0x2d, 0x70, 0x66, 0x19, 0x66, 0x95, 0xad, 0xd8, 0xc6, 0x96, 0x06, 0x50, 0xfc, 0xf9, - 0x14, 0x1a, 0x98, 0x23, 0xba, 0x41, 0x47, 0xc8, 0x60, 0x2f, 0x5f, 0x90, 0x4f, 0x3d, 0x1c, 0x5f, - 0x90, 0xf1, 0x75, 0x56, 0x99, 0xa8, 0x28, 0xbc, 0x7e, 0x7c, 0x0b, 0xe5, 0xa7, 0x75, 0x8f, 0xac, - 0xd9, 0xce, 0x16, 0x78, 0xb7, 0x8c, 0x86, 0xae, 0xcd, 0x92, 0xfe, 0xf8, 0x44, 0xec, 0x66, 0xac, - 0xc1, 0x7f, 0x69, 0x41, 0x61, 0x2a, 0x16, 0x9e, 0x6e, 0x64, 0x28, 0x14, 0x0b, 0xcb, 0x2b, 0x12, - 0x64, 0x15, 0x09, 0x8e, 0x95, 0x87, 0x93, 0x8f, 0x95, 0xc1, 0x7a, 0x04, 0x0f, 0x38, 0x08, 0xe6, - 0x3b, 0x02, 0x8b, 0x3e, 0xb3, 0x1e, 0x01, 0x0a, 0xb1, 0x7c, 0x35, 0x81, 0x44, 0xfd, 0x7a, 0x3f, - 0x4a, 0x7c, 0x82, 0x72, 0xa2, 0xe4, 0x27, 0x4a, 0x1e, 0x2a, 0x79, 0x39, 0xa6, 0xe4, 0x13, 0xf1, - 0x47, 0x4d, 0xef, 0x53, 0x0d, 0xff, 0xa1, 0x6c, 0xec, 0x49, 0xe4, 0xa3, 0xbd, 0xbb, 0x0c, 0xa5, - 0xd7, 0xbf, 0xab, 0xf4, 0x82, 0x01, 0x91, 0xdb, 0x75, 0x40, 0x0c, 0xec, 0x75, 0x40, 0xe4, 0xbb, - 0x0e, 0x88, 0x50, 0x41, 0x06, 0xbb, 0x2a, 0x48, 0x85, 0x0f, 0x1a, 0xd4, 0x3b, 0x50, 0xfc, 0x85, - 0x9d, 0xed, 0xe2, 0x28, 0x1d, 0x4d, 0x89, 0x21, 0xe2, 0x81, 0x85, 0xfa, 0xb5, 0x6c, 0x8f, 0x77, - 0xcc, 0x47, 0xa2, 0x23, 0xcf, 0xa2, 0x4c, 0xa9, 0xdd, 0xe6, 0xfa, 0x71, 0x4a, 0x78, 0x42, 0xdd, - 0xa5, 0x14, 0xa5, 0xc6, 0x2f, 0xa1, 0x4c, 0xe9, 0x5e, 0x2d, 0x1a, 0x8d, 0xb9, 0x74, 0xaf, 0xc6, - 0xbf, 0xa4, 0x6b, 0xd9, 0x7b, 0x35, 0xfc, 0x72, 0x18, 0x16, 0x69, 0xbd, 0x63, 0x6d, 0xf0, 0x8d, - 0x22, 0x77, 0x82, 0xf5, 0x3d, 0x6d, 0x1a, 0x14, 0x45, 0xb7, 0x8b, 0x11, 0xda, 0x88, 0x36, 0xe5, - 0xf6, 0xae, 0x4d, 0x03, 0xbb, 0x6a, 0x53, 0x7e, 0xaf, 0xda, 0x34, 0xb8, 0x07, 0x6d, 0x42, 0xbb, - 0x6a, 0xd3, 0xd0, 0xe1, 0xb5, 0xa9, 0x8d, 0x26, 0xe2, 0xb1, 0x27, 0x02, 0x8d, 0xd0, 0x10, 0x8e, - 0x63, 0xb9, 0x63, 0x09, 0x5c, 0xfd, 0x77, 0x18, 0xb6, 0xce, 0xd2, 0x02, 0x45, 0x93, 0xea, 0x68, - 0x09, 0xa5, 0xd5, 0x9f, 0x4b, 0x77, 0x0f, 0x99, 0x71, 0x3c, 0xa7, 0xb8, 0x6f, 0x4d, 0x94, 0x52, - 0x56, 0x7e, 0xc2, 0xd4, 0x5d, 0xca, 0x11, 0xb6, 0x49, 0x32, 0xfb, 0x6a, 0xaa, 0x5b, 0x1c, 0x8f, - 0x43, 0x49, 0xec, 0xc3, 0x71, 0x67, 0x35, 0xf0, 0x9e, 0x77, 0x65, 0x2f, 0xb5, 0x68, 0x96, 0x99, - 0xcc, 0x01, 0xb3, 0xcc, 0xfc, 0x5a, 0x0a, 0x9d, 0xba, 0xdd, 0x59, 0x21, 0xdc, 0x39, 0x2d, 0x68, - 0xc6, 0x3b, 0x08, 0x51, 0x30, 0x77, 0x62, 0x49, 0x81, 0x13, 0xcb, 0x47, 0xc5, 0x18, 0x1c, 0x91, - 0x02, 0x93, 0x21, 0x35, 0x73, 0x60, 0xb9, 0xe8, 0xbb, 0x58, 0x6e, 0x74, 0x56, 0x48, 0x3d, 0xe6, - 0xc9, 0x22, 0x70, 0x9f, 0x78, 0x85, 0x39, 0xaf, 0x1f, 0xd4, 0x69, 0xe4, 0x67, 0xd2, 0x5d, 0xc3, - 0x9e, 0x1c, 0x89, 0xee, 0x8a, 0xd9, 0xf2, 0x32, 0x07, 0xcc, 0x96, 0xf7, 0xe9, 0xc4, 0x5e, 0xe1, - 0xfa, 0xfb, 0x58, 0x8f, 0x7e, 0x88, 0x70, 0x4c, 0xe2, 0x92, 0x2c, 0xb0, 0x23, 0x1c, 0xec, 0xef, - 0x7b, 0x81, 0xfd, 0x76, 0xaa, 0x6b, 0x78, 0x9a, 0xe3, 0x2a, 0x30, 0xf5, 0x3f, 0x67, 0xfc, 0xa8, - 0x38, 0x87, 0xfa, 0x84, 0x6b, 0x68, 0x90, 0x87, 0xfe, 0x97, 0x7d, 0x6b, 0xf9, 0x51, 0x1e, 0x1c, - 0x0d, 0x07, 0x04, 0x74, 0x99, 0xf7, 0xa3, 0x76, 0x04, 0x79, 0x89, 0x60, 0x99, 0x37, 0x39, 0x94, - 0xd2, 0x0b, 0x24, 0x74, 0x21, 0x9f, 0x79, 0x60, 0x7a, 0x60, 0x15, 0xd0, 0xbe, 0xcc, 0xb0, 0x85, - 0x9c, 0x3c, 0x30, 0x3d, 0x66, 0x13, 0x04, 0x68, 0xba, 0x48, 0x0b, 0xf9, 0xbf, 0xf9, 0x22, 0xed, - 0xf2, 0x1c, 0x24, 0xfc, 0x31, 0xd7, 0x35, 0x34, 0xc8, 0x1d, 0x56, 0xb9, 0x9b, 0x09, 0x6f, 0x2d, - 0x77, 0x71, 0x85, 0xd6, 0x06, 0x04, 0x94, 0xa3, 0x46, 0xd6, 0x42, 0xc7, 0x3a, 0xe0, 0xe8, 0x00, - 0x44, 0xe3, 0x18, 0x7c, 0x03, 0x8d, 0xd6, 0x3c, 0xdd, 0x32, 0x74, 0xc7, 0x58, 0xea, 0x78, 0xed, - 0x8e, 0x27, 0x1a, 0xa5, 0xae, 0x67, 0xd8, 0x1d, 0x4f, 0x8b, 0x50, 0xe0, 0x8f, 0x41, 0xe6, 0x7e, - 0x80, 0xcc, 0x38, 0x8e, 0xed, 0x88, 0x96, 0x87, 0xeb, 0x19, 0xc4, 0x71, 0x34, 0x99, 0x00, 0x7f, - 0x1c, 0x8d, 0x54, 0xac, 0xfb, 0x76, 0x83, 0x85, 0xfb, 0xd5, 0xe6, 0xb9, 0x1d, 0x02, 0x0f, 0xa4, - 0xcc, 0x00, 0x51, 0xef, 0x38, 0x4d, 0x4d, 0x26, 0x54, 0x77, 0xd2, 0xf1, 0xe0, 0x41, 0x8f, 0xee, - 0xa6, 0xe5, 0xaa, 0xec, 0x4c, 0x07, 0x1e, 0xa4, 0x60, 0x10, 0x8a, 0xbe, 0xbc, 0xcc, 0x2e, 0xbc, - 0x81, 0xf2, 0xb7, 0xc9, 0x16, 0xf3, 0xfb, 0xcc, 0x85, 0xae, 0xc2, 0x1b, 0x1c, 0x26, 0x9e, 0xb8, - 0xfa, 0x74, 0xea, 0xaf, 0xa6, 0xe3, 0x61, 0x91, 0x1e, 0x5d, 0x61, 0x7f, 0x0c, 0x0d, 0x80, 0x28, - 0x2b, 0xfe, 0x91, 0x3f, 0x08, 0x10, 0xc4, 0x2d, 0x7b, 0x20, 0xfb, 0x64, 0xea, 0x4f, 0xe4, 0xa2, - 0xb1, 0xb2, 0x1e, 0x5d, 0xe9, 0x7d, 0x02, 0x0d, 0x4d, 0xdb, 0x96, 0x6b, 0xba, 0x1e, 0xb1, 0x1a, - 0xbe, 0xc2, 0x9e, 0xa7, 0x06, 0x55, 0x23, 0x04, 0x8b, 0x2f, 0x83, 0x04, 0xea, 0x83, 0x28, 0x2f, - 0x7e, 0x1e, 0x0d, 0x82, 0xc8, 0xc1, 0x4f, 0x5a, 0xc8, 0xba, 0xb6, 0x42, 0x81, 0x51, 0x27, 0xe9, - 0x90, 0x14, 0xdf, 0x41, 0xf9, 0xe9, 0x75, 0xb3, 0x69, 0x38, 0xc4, 0xe2, 0xe9, 0x45, 0x9f, 0x48, - 0x8e, 0x6c, 0x36, 0x09, 0xff, 0x02, 0x2d, 0x6b, 0x4e, 0x83, 0x17, 0x93, 0xde, 0x46, 0x71, 0xd8, - 0xc4, 0x0f, 0xa4, 0x11, 0x0a, 0x0b, 0xe0, 0xc7, 0x51, 0xda, 0x7f, 0x80, 0xcb, 0xdc, 0x54, 0x24, - 0x0d, 0x4a, 0xc3, 0x52, 0xc1, 0xc7, 0x76, 0x7a, 0xd7, 0xb1, 0x7d, 0x07, 0xe5, 0xd8, 0x89, 0x17, - 0x78, 0x92, 0x0b, 0xe1, 0x7b, 0xba, 0x36, 0x78, 0x12, 0xe8, 0xd9, 0x66, 0x16, 0x2c, 0x4f, 0xc9, - 0x2b, 0x9b, 0x31, 0x9b, 0x68, 0xa0, 0x7e, 0xf8, 0x0b, 0x5f, 0x46, 0x59, 0x90, 0x62, 0x0a, 0xf6, - 0xb1, 0x30, 0x4b, 0x47, 0xe4, 0x07, 0x78, 0xda, 0x4d, 0xd3, 0xb6, 0xe5, 0xd1, 0xaa, 0xa1, 0xd5, - 0xc3, 0x5c, 0x2e, 0x1c, 0x26, 0xc9, 0x85, 0xc3, 0xd4, 0x7f, 0x96, 0x4e, 0x88, 0xe2, 0xf6, 0xe8, - 0x0e, 0x93, 0x17, 0x11, 0x82, 0x87, 0xd6, 0x54, 0x9e, 0xfe, 0x13, 0x0d, 0x18, 0x25, 0xc0, 0x08, - 0xd4, 0x56, 0xda, 0x76, 0x84, 0xc4, 0xea, 0x6f, 0xa4, 0x62, 0xa1, 0xbf, 0x8e, 0x6b, 0x96, 0x6c, - 0xf9, 0x5b, 0x8e, 0x77, 0xc6, 0x6f, 0xf5, 0xeb, 0xe9, 0xa4, 0x40, 0x68, 0xc7, 0x53, 0xc5, 0xc3, - 0xd4, 0x9d, 0xd9, 0x7d, 0xa4, 0xee, 0x7c, 0x1b, 0x8d, 0x45, 0xc2, 0x83, 0xf1, 0xcc, 0x66, 0x97, - 0x7b, 0xc7, 0x19, 0xeb, 0xfe, 0x44, 0x5f, 0x22, 0x53, 0xff, 0x6f, 0xaa, 0x77, 0x70, 0xb8, 0x23, - 0x57, 0x9d, 0x04, 0x01, 0x64, 0xfe, 0x6c, 0x04, 0xf0, 0x10, 0xb6, 0xc1, 0xc7, 0x5b, 0x00, 0xef, - 0x93, 0xc9, 0xe3, 0x9b, 0x2d, 0x80, 0x9f, 0x48, 0xed, 0x1a, 0xdb, 0xef, 0xa8, 0x65, 0xa0, 0xfe, - 0x87, 0x54, 0x62, 0x0c, 0xbe, 0x43, 0xb5, 0xeb, 0x65, 0x94, 0x63, 0x6e, 0x35, 0xbc, 0x55, 0x42, - 0xd6, 0x02, 0x0a, 0xed, 0x96, 0x42, 0x9b, 0x61, 0xf1, 0x3c, 0x1a, 0x60, 0x6d, 0x30, 0x78, 0x6f, - 0x7c, 0xa8, 0x47, 0x20, 0x40, 0xa3, 0xdb, 0xe4, 0xc8, 0xd1, 0xea, 0xaf, 0xa7, 0x62, 0x21, 0x01, - 0x8f, 0xf0, 0xdb, 0xc2, 0xa9, 0x3a, 0xb3, 0xf7, 0xa9, 0x5a, 0xfd, 0xfd, 0x74, 0x72, 0x44, 0xc2, - 0x23, 0xfc, 0x90, 0x87, 0x71, 0x9c, 0x76, 0xb0, 0x75, 0x6b, 0x19, 0x8d, 0xca, 0xb2, 0xe0, 0xcb, - 0xd6, 0xa5, 0xe4, 0xb8, 0x8c, 0x5d, 0x5a, 0x11, 0xe1, 0xa1, 0xbe, 0x97, 0x8a, 0x07, 0x53, 0x3c, - 0xf2, 0xf9, 0xe9, 0x60, 0xda, 0x22, 0x7f, 0xca, 0xfb, 0x64, 0xad, 0x79, 0x18, 0x9f, 0xf2, 0x3e, - 0x59, 0x35, 0x0e, 0xf6, 0x29, 0x3f, 0x95, 0xee, 0x16, 0x8b, 0xf2, 0xc8, 0x3f, 0xe8, 0x2d, 0x51, - 0xc8, 0xac, 0x65, 0xfc, 0xd3, 0x1e, 0xef, 0x16, 0xfc, 0xb1, 0x0b, 0xcf, 0x18, 0x9f, 0x83, 0x8d, - 0xf1, 0x44, 0x61, 0xbd, 0x4f, 0x14, 0xf9, 0x78, 0x08, 0xeb, 0x7d, 0x32, 0x54, 0xde, 0x7f, 0xc2, - 0xfa, 0xe5, 0xf4, 0x5e, 0x03, 0xa0, 0x9e, 0x08, 0x2f, 0x26, 0xbc, 0x2f, 0xa5, 0xe3, 0x81, 0x79, - 0x8f, 0x5c, 0x4c, 0xb3, 0x28, 0xc7, 0x43, 0x04, 0x77, 0x15, 0x0e, 0xc3, 0x77, 0xb3, 0x68, 0xf8, - 0x77, 0x84, 0x79, 0xd5, 0xb3, 0x7b, 0xcf, 0xab, 0xae, 0xfe, 0x71, 0x2a, 0x12, 0xc5, 0xf6, 0x48, - 0x8e, 0x10, 0x0e, 0xb4, 0x24, 0xe1, 0x57, 0xfc, 0xc3, 0xcc, 0x6c, 0x24, 0x41, 0x68, 0xf0, 0x3d, - 0x65, 0xe2, 0xe9, 0x66, 0x33, 0x5a, 0x9e, 0xc7, 0x04, 0xf8, 0xd5, 0x34, 0x1a, 0x8f, 0x91, 0xe2, - 0xcb, 0x52, 0x94, 0x1c, 0x38, 0x96, 0x8c, 0x38, 0x8f, 0xb3, 0x78, 0x39, 0xfb, 0x38, 0x49, 0xbd, - 0x8c, 0xb2, 0x65, 0x7d, 0x8b, 0x7d, 0x5b, 0x3f, 0x63, 0x69, 0xe8, 0x5b, 0xe2, 0x89, 0x1b, 0xe0, - 0xf1, 0x0a, 0x3a, 0xc3, 0xee, 0x43, 0x4c, 0xdb, 0x5a, 0x36, 0x5b, 0xa4, 0x62, 0x2d, 0x98, 0xcd, - 0xa6, 0xe9, 0xf2, 0x4b, 0xbd, 0x6b, 0x3b, 0xdb, 0xc5, 0x2b, 0x9e, 0xed, 0xe9, 0xcd, 0x3a, 0xf1, - 0xc9, 0xea, 0x9e, 0xd9, 0x22, 0x75, 0xd3, 0xaa, 0xb7, 0x80, 0x52, 0x60, 0x99, 0xcc, 0x0a, 0x57, - 0x58, 0xb4, 0xc9, 0x5a, 0x43, 0xb7, 0x2c, 0x62, 0x54, 0xac, 0xa9, 0x2d, 0x8f, 0xb0, 0xcb, 0xc0, - 0x0c, 0x3b, 0x12, 0x64, 0x6f, 0xc3, 0x19, 0x9a, 0x32, 0x5e, 0xa1, 0x04, 0x5a, 0x42, 0x21, 0xf5, - 0x57, 0xb2, 0x09, 0x01, 0x8c, 0x8f, 0x91, 0xfa, 0xf8, 0x3d, 0x9d, 0xdd, 0xa5, 0xa7, 0xaf, 0xa3, - 0x81, 0xbb, 0xc4, 0x81, 0xf3, 0x2d, 0x76, 0xc1, 0x00, 0xce, 0xec, 0xf7, 0x19, 0x48, 0xbc, 0xa1, - 0xe1, 0x54, 0xb8, 0x89, 0x26, 0x96, 0x69, 0x37, 0x25, 0x77, 0x66, 0xee, 0x00, 0x9d, 0xd9, 0x83, - 0x1f, 0x7e, 0x13, 0x9d, 0x03, 0x6c, 0x42, 0xb7, 0x0e, 0x40, 0x55, 0x10, 0x39, 0x8a, 0x55, 0x95, - 0xdc, 0xb9, 0xdd, 0xca, 0xe3, 0xb7, 0xd0, 0x70, 0x30, 0x40, 0x4c, 0xe2, 0xf2, 0x9b, 0x8b, 0x1e, - 0xe3, 0x8c, 0x85, 0x65, 0xa3, 0x60, 0x70, 0x21, 0x93, 0x43, 0x7b, 0x49, 0xbc, 0xd4, 0x7f, 0x9f, - 0xea, 0x15, 0x48, 0xf9, 0xc8, 0x67, 0xe5, 0x57, 0xd0, 0x80, 0xc1, 0x3e, 0x8a, 0xeb, 0x54, 0xef, - 0x50, 0xcb, 0x8c, 0x54, 0xf3, 0xcb, 0xa8, 0xbf, 0x97, 0xea, 0x19, 0xbf, 0xf9, 0xb8, 0x7f, 0xde, - 0x97, 0x32, 0x5d, 0x3e, 0x8f, 0x4f, 0xa2, 0x57, 0x51, 0xc1, 0xb4, 0x3c, 0xb2, 0xc6, 0x52, 0xb3, - 0xd5, 0xc3, 0xf0, 0x53, 0xda, 0x98, 0x00, 0x87, 0xd1, 0x75, 0x13, 0x9d, 0xf5, 0x1d, 0x1f, 0x1d, - 0xdf, 0x43, 0xcc, 0xad, 0x77, 0x1c, 0x93, 0x8d, 0x4b, 0xed, 0xb4, 0x1b, 0x71, 0x1f, 0x73, 0xef, - 0x38, 0x26, 0xad, 0x40, 0xf7, 0xd6, 0x89, 0xa5, 0xd7, 0x37, 0x6d, 0x67, 0x03, 0x62, 0x7f, 0xb2, - 0xc1, 0xa9, 0x8d, 0x31, 0xf8, 0x3d, 0x1f, 0x8c, 0x9f, 0x44, 0x23, 0x6b, 0xcd, 0x0e, 0x09, 0xa2, - 0x2d, 0xb2, 0xbb, 0x3e, 0x6d, 0x98, 0x02, 0x83, 0x1b, 0x92, 0x8b, 0x08, 0x01, 0x91, 0x07, 0xd1, - 0xb5, 0xe1, 0x62, 0x4f, 0x1b, 0xa4, 0x90, 0x65, 0xde, 0x5d, 0x13, 0x4c, 0xab, 0x99, 0x90, 0xea, - 0x4d, 0xdb, 0x5a, 0xab, 0x7b, 0xc4, 0x69, 0x41, 0x43, 0xc1, 0x99, 0x41, 0x3b, 0x0b, 0x14, 0x70, - 0x75, 0xe2, 0xce, 0xdb, 0xd6, 0xda, 0x32, 0x71, 0x5a, 0xb4, 0xa9, 0xd7, 0x10, 0xe6, 0x4d, 0x75, - 0xe0, 0xd0, 0x83, 0x7d, 0x1c, 0x78, 0x33, 0x68, 0xfc, 0x23, 0xd8, 0x69, 0x08, 0x7c, 0x58, 0x11, - 0x0d, 0xb1, 0x90, 0x73, 0x4c, 0x68, 0xe0, 0xc2, 0xa0, 0x21, 0x06, 0x02, 0x79, 0x9d, 0x45, 0xdc, - 0xbb, 0x82, 0x79, 0x75, 0x6b, 0xfc, 0x97, 0xfa, 0x85, 0x4c, 0x52, 0xc8, 0xe9, 0x43, 0x29, 0x5a, - 0x38, 0xad, 0xa6, 0xf7, 0x35, 0xad, 0x8e, 0x59, 0x9d, 0x56, 0x5d, 0x6f, 0xb7, 0xeb, 0xab, 0x66, - 0x13, 0x9e, 0x55, 0xc1, 0xc2, 0xa7, 0x8d, 0x58, 0x9d, 0x56, 0xa9, 0xdd, 0x9e, 0x65, 0x40, 0xfc, - 0x14, 0x1a, 0xa7, 0x74, 0xd0, 0x49, 0x01, 0x65, 0x16, 0x28, 0x29, 0x03, 0x88, 0xd9, 0xea, 0xd3, - 0x9e, 0x47, 0x79, 0xce, 0x93, 0xad, 0x55, 0xfd, 0xda, 0x00, 0x63, 0xe6, 0xd2, 0x9e, 0x0b, 0xd8, - 0xb0, 0xc9, 0xb5, 0x5f, 0x1b, 0xf4, 0xcb, 0x43, 0x64, 0x62, 0xab, 0xd3, 0x62, 0x11, 0xb1, 0x06, - 0x00, 0x19, 0xfc, 0xc6, 0x97, 0xd1, 0x28, 0xe5, 0x12, 0x08, 0x8c, 0x05, 0x73, 0xed, 0xd7, 0x22, - 0x50, 0x7c, 0x03, 0x9d, 0x96, 0x20, 0xcc, 0x06, 0x65, 0xcf, 0x04, 0xfa, 0xb5, 0x44, 0x9c, 0xfa, - 0x5e, 0x26, 0x1e, 0x51, 0xfb, 0x48, 0xd6, 0xc6, 0x39, 0x84, 0x78, 0xc0, 0xfc, 0xf0, 0x82, 0x26, - 0xf0, 0x5a, 0x0e, 0x31, 0x5d, 0x78, 0x08, 0x65, 0xf1, 0x55, 0x94, 0x67, 0x5f, 0x54, 0x29, 0xf3, - 0x35, 0x13, 0xdc, 0x8c, 0xdc, 0xb6, 0xb9, 0xba, 0x0a, 0x3e, 0x49, 0x01, 0x1a, 0x5f, 0x46, 0x03, - 0xe5, 0xc5, 0x5a, 0xad, 0xb4, 0xe8, 0xdf, 0x36, 0xc2, 0x1b, 0x05, 0xc3, 0x72, 0xeb, 0xae, 0x6e, - 0xb9, 0x9a, 0x8f, 0xc4, 0x4f, 0xa2, 0x5c, 0xa5, 0x0a, 0x64, 0xec, 0xe5, 0xdd, 0xd0, 0xce, 0x76, - 0x71, 0xc0, 0x6c, 0x33, 0x2a, 0x8e, 0x82, 0x7a, 0xef, 0x56, 0xca, 0xc2, 0x95, 0x3b, 0xab, 0xf7, - 0xbe, 0x69, 0xc0, 0xd5, 0xa5, 0x16, 0xa0, 0xf1, 0x73, 0x68, 0xb8, 0x46, 0x1c, 0x53, 0x6f, 0x2e, - 0x76, 0x60, 0xbb, 0xc1, 0xdc, 0x8c, 0xc6, 0x77, 0xb6, 0x8b, 0x23, 0x2e, 0xc0, 0xeb, 0x16, 0x20, - 0x34, 0x89, 0x0c, 0x5f, 0x40, 0xd9, 0x39, 0xd3, 0xf2, 0xdd, 0xe0, 0xc1, 0x4f, 0x7a, 0xdd, 0xb4, - 0x3c, 0x0d, 0xa0, 0xea, 0xf7, 0xa6, 0x93, 0x63, 0x9a, 0x1f, 0xc1, 0xd8, 0x3a, 0xe0, 0x6d, 0x61, - 0x44, 0x09, 0xb2, 0x07, 0x57, 0x02, 0xf5, 0xfb, 0xd3, 0xbb, 0x84, 0x47, 0x7f, 0x24, 0xa5, 0xf2, - 0xe5, 0x74, 0xef, 0x08, 0xf5, 0x8f, 0xa2, 0x50, 0x9e, 0x5a, 0x60, 0xb1, 0x27, 0x6f, 0x9b, 0x96, - 0x81, 0xcf, 0xa3, 0x33, 0x77, 0x6a, 0x33, 0x5a, 0xfd, 0x76, 0x65, 0xb1, 0x5c, 0xbf, 0xb3, 0x58, - 0xab, 0xce, 0x4c, 0x57, 0x66, 0x2b, 0x33, 0xe5, 0x42, 0x1f, 0x3e, 0x85, 0xc6, 0x42, 0xd4, 0xdc, - 0x9d, 0x85, 0xd2, 0x62, 0x21, 0x85, 0xc7, 0xd1, 0x48, 0x08, 0x9c, 0x5a, 0x5a, 0x2e, 0xa4, 0x9f, - 0xfa, 0x08, 0x1a, 0x82, 0xc5, 0xb5, 0xc4, 0x66, 0xa3, 0x61, 0x94, 0x5f, 0x9a, 0xaa, 0xcd, 0x68, - 0x77, 0x81, 0x09, 0x42, 0xb9, 0xf2, 0xcc, 0x22, 0x65, 0x98, 0x7a, 0xea, 0x7f, 0xa5, 0x10, 0xaa, - 0xcd, 0x2e, 0x57, 0x39, 0xe1, 0x10, 0x1a, 0xa8, 0x2c, 0xde, 0x2d, 0xcd, 0x57, 0x28, 0x5d, 0x1e, - 0x65, 0x97, 0xaa, 0x33, 0xb4, 0x86, 0x41, 0xd4, 0x3f, 0x3d, 0xbf, 0x54, 0x9b, 0x29, 0xa4, 0x29, - 0x50, 0x9b, 0x29, 0x95, 0x0b, 0x19, 0x0a, 0xbc, 0xa7, 0x55, 0x96, 0x67, 0x0a, 0x59, 0xfa, 0xe7, - 0x7c, 0x6d, 0xb9, 0xb4, 0x5c, 0xe8, 0xa7, 0x7f, 0xce, 0xc2, 0x9f, 0x39, 0xca, 0xac, 0x36, 0xb3, - 0x0c, 0x3f, 0x06, 0x68, 0x13, 0x66, 0xfd, 0x5f, 0x79, 0x8a, 0xa2, 0xac, 0xcb, 0x15, 0xad, 0x30, - 0x48, 0x7f, 0x50, 0x96, 0xf4, 0x07, 0xa2, 0x8d, 0xd3, 0x66, 0x16, 0x96, 0xee, 0xce, 0x14, 0x86, - 0x28, 0xaf, 0x85, 0xdb, 0x14, 0x3c, 0x4c, 0xff, 0xd4, 0x16, 0xe8, 0x9f, 0x23, 0x94, 0x93, 0x36, - 0x53, 0x9a, 0xaf, 0x96, 0x96, 0xe7, 0x0a, 0xa3, 0xb4, 0x3d, 0xc0, 0x73, 0x8c, 0x95, 0x5c, 0x2c, - 0x2d, 0xcc, 0x14, 0x0a, 0x9c, 0xa6, 0x3c, 0x5f, 0x59, 0xbc, 0x5d, 0x18, 0x87, 0x86, 0xbc, 0xb9, - 0x00, 0x3f, 0x30, 0x2d, 0x00, 0x7f, 0x9d, 0x7a, 0xea, 0x5b, 0x50, 0x6e, 0xa9, 0x06, 0x53, 0xe1, - 0x39, 0x74, 0x6a, 0xa9, 0x56, 0x5f, 0x7e, 0xb3, 0x3a, 0x13, 0x91, 0xf7, 0x38, 0x1a, 0xf1, 0x11, - 0xf3, 0x95, 0xc5, 0x3b, 0x9f, 0x62, 0xd2, 0xf6, 0x41, 0x0b, 0xa5, 0xe9, 0xa5, 0x5a, 0x21, 0x4d, - 0x7b, 0xc5, 0x07, 0xdd, 0xab, 0x2c, 0x96, 0x97, 0xee, 0xd5, 0x0a, 0x99, 0xa7, 0xee, 0xfb, 0xa9, - 0xb2, 0x96, 0x1c, 0x73, 0xcd, 0xb4, 0xf0, 0x45, 0x74, 0xbe, 0x3c, 0x73, 0xb7, 0x32, 0x3d, 0x53, - 0x5f, 0xd2, 0x2a, 0xb7, 0x2a, 0x8b, 0x91, 0x9a, 0xce, 0xa0, 0x71, 0x19, 0x5d, 0xaa, 0x56, 0x0a, - 0x29, 0x7c, 0x16, 0x61, 0x19, 0xfc, 0x7a, 0x69, 0x61, 0xb6, 0x90, 0xc6, 0x0a, 0x3a, 0x2d, 0xc3, - 0x2b, 0x8b, 0xcb, 0x77, 0x16, 0x67, 0x0a, 0x99, 0xa7, 0xfe, 0x66, 0x0a, 0x9d, 0x49, 0x7c, 0xdd, - 0x89, 0x55, 0x74, 0x69, 0x66, 0xbe, 0x54, 0x5b, 0xae, 0x4c, 0xd7, 0x66, 0x4a, 0xda, 0xf4, 0x5c, - 0x7d, 0xba, 0xb4, 0x3c, 0x73, 0x6b, 0x49, 0x7b, 0xb3, 0x7e, 0x6b, 0x66, 0x71, 0x46, 0x2b, 0xcd, - 0x17, 0xfa, 0xf0, 0x93, 0xa8, 0xd8, 0x85, 0xa6, 0x36, 0x33, 0x7d, 0x47, 0xab, 0x2c, 0xbf, 0x59, - 0x48, 0xe1, 0x27, 0xd0, 0xc5, 0xae, 0x44, 0xf4, 0x77, 0x21, 0x8d, 0x2f, 0xa1, 0x89, 0x6e, 0x24, - 0x6f, 0xcc, 0x17, 0x32, 0x4f, 0xfd, 0x70, 0x0a, 0xe1, 0xf8, 0xf3, 0x3c, 0xfc, 0x38, 0xba, 0x40, - 0xf5, 0xa2, 0xde, 0xbd, 0x81, 0x4f, 0xa0, 0x8b, 0x89, 0x14, 0x42, 0xf3, 0x8a, 0xe8, 0xb1, 0x2e, - 0x24, 0xbc, 0x71, 0x17, 0x90, 0x92, 0x4c, 0x40, 0x9b, 0x36, 0x55, 0x7e, 0xef, 0x3f, 0x5e, 0xea, - 0x7b, 0xef, 0x0f, 0x2e, 0xa5, 0x7e, 0xeb, 0x0f, 0x2e, 0xa5, 0x7e, 0xff, 0x0f, 0x2e, 0xa5, 0xde, - 0xba, 0xb1, 0x9f, 0xd7, 0x8b, 0x6c, 0xf4, 0xaf, 0xe4, 0xe0, 0x9d, 0xce, 0xb3, 0xff, 0x2f, 0x00, - 0x00, 0xff, 0xff, 0x0e, 0x80, 0xf3, 0x42, 0x80, 0x3d, 0x01, 0x00, + // 14563 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6d, 0x70, 0x24, 0xc7, + 0x75, 0x18, 0xf6, 0x03, 0x8b, 0x45, 0xe3, 0x6b, 0xd1, 0xf7, 0x35, 0x07, 0xde, 0xdd, 0x92, 0x43, + 0xe9, 0x74, 0x47, 0x1d, 0x71, 0xe2, 0xf1, 0x48, 0x8a, 0x14, 0x29, 0x72, 0x81, 0x05, 0x0e, 0xcb, + 0xc3, 0xc7, 0x72, 0x16, 0x77, 0x27, 0x4a, 0x16, 0xd7, 0x83, 0x9d, 0x06, 0x30, 0xc4, 0xee, 0xcc, + 0x6a, 0x66, 0xf6, 0x70, 0x60, 0xbe, 0x2c, 0xc7, 0x5f, 0x72, 0x64, 0x45, 0x91, 0xe3, 0xaf, 0xd8, + 0x95, 0xd8, 0x49, 0xa5, 0xca, 0x71, 0x39, 0x76, 0x1c, 0xa7, 0x6c, 0xcb, 0x8e, 0x2a, 0x76, 0x94, + 0x54, 0xe8, 0x28, 0x4e, 0xd9, 0x4e, 0xe2, 0x4a, 0x25, 0x0e, 0xe4, 0x38, 0x71, 0x7e, 0xa0, 0x92, + 0x2a, 0x57, 0x45, 0x95, 0x38, 0x8e, 0x9d, 0x4a, 0xf5, 0xeb, 0x9e, 0x99, 0xee, 0x99, 0xd9, 0xc5, + 0xd7, 0xc9, 0x20, 0x78, 0xf8, 0x73, 0x87, 0x7d, 0xef, 0xf5, 0xeb, 0x9e, 0xd7, 0xaf, 0xbb, 0x5f, + 0x77, 0xbf, 0x7e, 0x0f, 0x5d, 0xf5, 0x48, 0x93, 0xb4, 0x6d, 0xc7, 0xbb, 0xde, 0x24, 0x6b, 0x7a, + 0x63, 0xeb, 0xba, 0xb7, 0xd5, 0x26, 0xee, 0x75, 0x72, 0x9f, 0x58, 0x9e, 0xff, 0xdf, 0x64, 0xdb, + 0xb1, 0x3d, 0x1b, 0xe7, 0xd8, 0xaf, 0x89, 0xd3, 0x6b, 0xf6, 0x9a, 0x0d, 0xa0, 0xeb, 0xf4, 0x2f, + 0x86, 0x9d, 0xb8, 0xb0, 0x66, 0xdb, 0x6b, 0x4d, 0x72, 0x1d, 0x7e, 0xad, 0x74, 0x56, 0xaf, 0xbb, + 0x9e, 0xd3, 0x69, 0x78, 0x1c, 0x5b, 0x8c, 0x62, 0x3d, 0xb3, 0x45, 0x5c, 0x4f, 0x6f, 0xb5, 0x39, + 0xc1, 0xa5, 0x28, 0xc1, 0xa6, 0xa3, 0xb7, 0xdb, 0xc4, 0xe1, 0x95, 0x4f, 0x3c, 0x91, 0xdc, 0x4e, + 0xf8, 0x97, 0x93, 0x3c, 0x9d, 0x4c, 0xe2, 0x33, 0x8a, 0x70, 0x54, 0xbf, 0x94, 0x46, 0xf9, 0x05, + 0xe2, 0xe9, 0x86, 0xee, 0xe9, 0xf8, 0x02, 0xea, 0xaf, 0x58, 0x06, 0x79, 0xa0, 0xa4, 0x1e, 0x4f, + 0x5d, 0xc9, 0x4c, 0xe5, 0x76, 0xb6, 0x8b, 0x69, 0x62, 0x6a, 0x0c, 0x88, 0x2f, 0xa2, 0xec, 0xf2, + 0x56, 0x9b, 0x28, 0xe9, 0xc7, 0x53, 0x57, 0x06, 0xa7, 0x06, 0x77, 0xb6, 0x8b, 0xfd, 0x20, 0x0b, + 0x0d, 0xc0, 0xf8, 0x09, 0x94, 0xae, 0x94, 0x95, 0x0c, 0x20, 0xc7, 0x77, 0xb6, 0x8b, 0x23, 0x1d, + 0xd3, 0xb8, 0x66, 0xb7, 0x4c, 0x8f, 0xb4, 0xda, 0xde, 0x96, 0x96, 0xae, 0x94, 0xf1, 0x65, 0x94, + 0x9d, 0xb6, 0x0d, 0xa2, 0x64, 0x81, 0x08, 0xef, 0x6c, 0x17, 0x47, 0x1b, 0xb6, 0x41, 0x04, 0x2a, + 0xc0, 0xe3, 0xd7, 0x50, 0x76, 0xd9, 0x6c, 0x11, 0xa5, 0xff, 0xf1, 0xd4, 0x95, 0xa1, 0x1b, 0x13, + 0x93, 0x4c, 0x2a, 0x93, 0xbe, 0x54, 0x26, 0x97, 0x7d, 0xb1, 0x4d, 0x15, 0xde, 0xdd, 0x2e, 0xf6, + 0xed, 0x6c, 0x17, 0xb3, 0x54, 0x92, 0x5f, 0xfc, 0x7a, 0x31, 0xa5, 0x41, 0x49, 0xfc, 0x32, 0x1a, + 0x9a, 0x6e, 0x76, 0x5c, 0x8f, 0x38, 0x8b, 0x7a, 0x8b, 0x28, 0x39, 0xa8, 0x70, 0x62, 0x67, 0xbb, + 0x78, 0xb6, 0xc1, 0xc0, 0x75, 0x4b, 0x6f, 0x89, 0x15, 0x8b, 0xe4, 0xea, 0x2f, 0xa5, 0xd0, 0x58, + 0x8d, 0xb8, 0xae, 0x69, 0x5b, 0x81, 0x6c, 0x3e, 0x88, 0x06, 0x39, 0xa8, 0x52, 0x06, 0xf9, 0x0c, + 0x4e, 0x0d, 0xec, 0x6c, 0x17, 0x33, 0xae, 0x69, 0x68, 0x21, 0x06, 0x7f, 0x04, 0x0d, 0xdc, 0x33, + 0xbd, 0xf5, 0x85, 0xd9, 0x12, 0x97, 0xd3, 0xd9, 0x9d, 0xed, 0x22, 0xde, 0x34, 0xbd, 0xf5, 0x7a, + 0x6b, 0x55, 0x17, 0x2a, 0xf4, 0xc9, 0xf0, 0x3c, 0x2a, 0x54, 0x1d, 0xf3, 0xbe, 0xee, 0x91, 0xdb, + 0x64, 0xab, 0x6a, 0x37, 0xcd, 0xc6, 0x16, 0x97, 0xe2, 0xe3, 0x3b, 0xdb, 0xc5, 0x0b, 0x6d, 0x86, + 0xab, 0x6f, 0x90, 0xad, 0x7a, 0x1b, 0xb0, 0x02, 0x93, 0x58, 0x49, 0xf5, 0xab, 0xfd, 0x68, 0xf8, + 0x8e, 0x4b, 0x9c, 0xa0, 0xdd, 0x97, 0x51, 0x96, 0xfe, 0xe6, 0x4d, 0x06, 0x99, 0x77, 0x5c, 0xe2, + 0x88, 0x32, 0xa7, 0x78, 0x7c, 0x15, 0xf5, 0xcf, 0xdb, 0x6b, 0xa6, 0xc5, 0x9b, 0x7d, 0x6a, 0x67, + 0xbb, 0x38, 0xd6, 0xa4, 0x00, 0x81, 0x92, 0x51, 0xe0, 0x8f, 0xa3, 0xe1, 0x4a, 0x8b, 0xea, 0x90, + 0x6d, 0xe9, 0x9e, 0xed, 0xf0, 0xd6, 0x82, 0x74, 0x4d, 0x01, 0x2e, 0x14, 0x94, 0xe8, 0xf1, 0x4b, + 0x08, 0x95, 0xee, 0xd5, 0x34, 0xbb, 0x49, 0x4a, 0xda, 0x22, 0x57, 0x06, 0x28, 0xad, 0x6f, 0xba, + 0x75, 0xc7, 0x6e, 0x92, 0xba, 0xee, 0x88, 0xd5, 0x0a, 0xd4, 0x78, 0x06, 0x8d, 0x96, 0x1a, 0x0d, + 0xe2, 0xba, 0x1a, 0xf9, 0x4c, 0x87, 0xb8, 0x9e, 0xab, 0xf4, 0x3f, 0x9e, 0xb9, 0x32, 0x38, 0x75, + 0x71, 0x67, 0xbb, 0x78, 0x5e, 0x07, 0x4c, 0xdd, 0xe1, 0x28, 0x81, 0x45, 0xa4, 0x10, 0x9e, 0x42, + 0x23, 0xa5, 0x77, 0x3a, 0x0e, 0xa9, 0x18, 0xc4, 0xf2, 0x4c, 0x6f, 0x8b, 0x6b, 0xc8, 0x85, 0x9d, + 0xed, 0xa2, 0xa2, 0x53, 0x44, 0xdd, 0xe4, 0x18, 0x81, 0x89, 0x5c, 0x04, 0x2f, 0xa1, 0xf1, 0x5b, + 0xd3, 0xd5, 0x1a, 0x71, 0xee, 0x9b, 0x0d, 0x52, 0x6a, 0x34, 0xec, 0x8e, 0xe5, 0x29, 0x03, 0xc0, + 0xe7, 0x89, 0x9d, 0xed, 0xe2, 0xc5, 0xb5, 0x46, 0xbb, 0xee, 0x32, 0x6c, 0x5d, 0x67, 0x68, 0x81, + 0x59, 0xbc, 0x2c, 0xfe, 0x24, 0x1a, 0x59, 0x76, 0xa8, 0x16, 0x1a, 0x65, 0x42, 0xe1, 0x4a, 0x1e, + 0xf4, 0xff, 0xec, 0x24, 0x9f, 0x80, 0x18, 0xd4, 0xef, 0x59, 0xd6, 0x58, 0x8f, 0x15, 0xa8, 0x1b, + 0x80, 0x13, 0x1b, 0x2b, 0xb1, 0xc2, 0x04, 0x29, 0xf4, 0xe3, 0x4d, 0x87, 0x18, 0x31, 0x6d, 0x1b, + 0x84, 0x36, 0x5f, 0xdd, 0xd9, 0x2e, 0x7e, 0xd0, 0xe1, 0x34, 0xf5, 0x9e, 0x6a, 0xd7, 0x95, 0x15, + 0x9e, 0x41, 0x79, 0xaa, 0x4d, 0xb7, 0x4d, 0xcb, 0x50, 0xd0, 0xe3, 0xa9, 0x2b, 0xa3, 0x37, 0x0a, + 0x7e, 0xeb, 0x7d, 0xf8, 0xd4, 0xb9, 0x9d, 0xed, 0xe2, 0x29, 0xaa, 0x83, 0xf5, 0x0d, 0xd3, 0x12, + 0xa7, 0x88, 0xa0, 0xa8, 0xfa, 0xf3, 0x59, 0x34, 0x4a, 0x85, 0x23, 0xe8, 0x71, 0x89, 0x0e, 0x49, + 0x0a, 0xa1, 0x23, 0xd4, 0x6d, 0xeb, 0x0d, 0xc2, 0x55, 0x1a, 0xd8, 0x59, 0x3e, 0x50, 0x60, 0x17, + 0xa5, 0xc7, 0x57, 0x51, 0x9e, 0x81, 0x2a, 0x65, 0xae, 0xe5, 0x23, 0x3b, 0xdb, 0xc5, 0x41, 0x17, + 0x60, 0x75, 0xd3, 0xd0, 0x02, 0x34, 0x55, 0x33, 0xf6, 0xf7, 0x9c, 0xed, 0x7a, 0x94, 0x39, 0x57, + 0x72, 0x50, 0x33, 0x5e, 0x60, 0x9d, 0xa3, 0x44, 0x35, 0x93, 0x0b, 0xe1, 0x17, 0x11, 0x62, 0x90, + 0x92, 0x61, 0x38, 0x5c, 0xd3, 0xcf, 0xef, 0x6c, 0x17, 0xcf, 0x70, 0x16, 0xba, 0x61, 0x88, 0xc3, + 0x44, 0x20, 0xc6, 0x2d, 0x34, 0xcc, 0x7e, 0xcd, 0xeb, 0x2b, 0xa4, 0xc9, 0xd4, 0x7c, 0xe8, 0xc6, + 0x15, 0x5f, 0x9a, 0xb2, 0x74, 0x26, 0x45, 0xd2, 0x19, 0xcb, 0x73, 0xb6, 0xa6, 0x8a, 0x7c, 0x66, + 0x3c, 0xc7, 0xab, 0x6a, 0x02, 0x4e, 0x1c, 0x93, 0x62, 0x19, 0x3a, 0x61, 0xce, 0xda, 0xce, 0xa6, + 0xee, 0x18, 0xc4, 0x98, 0xda, 0x12, 0x27, 0xcc, 0x55, 0x1f, 0x5c, 0x5f, 0x11, 0x75, 0x40, 0x24, + 0xc7, 0xd3, 0x68, 0x84, 0x71, 0xab, 0x75, 0x56, 0xa0, 0xef, 0x07, 0x62, 0xd2, 0x72, 0x3b, 0x2b, + 0xd1, 0xfe, 0x96, 0xcb, 0x4c, 0xbc, 0x8a, 0xc6, 0x63, 0x9f, 0x81, 0x0b, 0x28, 0xb3, 0x41, 0xb6, + 0x58, 0x57, 0x6b, 0xf4, 0x4f, 0x7c, 0x1a, 0xf5, 0xdf, 0xd7, 0x9b, 0x1d, 0xbe, 0x0e, 0x69, 0xec, + 0xc7, 0x4b, 0xe9, 0x8f, 0xa6, 0xe8, 0xb4, 0x8d, 0xa7, 0x6d, 0xcb, 0x22, 0x0d, 0x4f, 0x9c, 0xb9, + 0x9f, 0x47, 0x83, 0xf3, 0x76, 0x43, 0x6f, 0x42, 0x1f, 0x30, 0x9d, 0x51, 0x76, 0xb6, 0x8b, 0xa7, + 0xa9, 0xf0, 0x27, 0x9b, 0x14, 0x23, 0xb4, 0x29, 0x24, 0xa5, 0x9d, 0xa7, 0x91, 0x96, 0xed, 0x11, + 0x28, 0x98, 0x0e, 0x3b, 0x0f, 0x0a, 0x3a, 0x80, 0x12, 0x3b, 0x2f, 0x24, 0xc6, 0xd7, 0x51, 0xbe, + 0x4a, 0x17, 0xab, 0x86, 0xdd, 0xe4, 0x8a, 0x03, 0xf3, 0x29, 0x2c, 0x60, 0xa2, 0xc2, 0xfb, 0x44, + 0xea, 0x1c, 0x1a, 0x9d, 0x6e, 0x9a, 0xc4, 0xf2, 0xc4, 0x56, 0xd3, 0xe1, 0x50, 0x5a, 0x23, 0x96, + 0x27, 0xb6, 0x1a, 0x06, 0x8e, 0x4e, 0xa1, 0x62, 0xab, 0x03, 0x52, 0xf5, 0x5f, 0x67, 0xd0, 0xf9, + 0xdb, 0x9d, 0x15, 0xe2, 0x58, 0xc4, 0x23, 0x2e, 0x5f, 0xd5, 0x02, 0xae, 0x8b, 0x68, 0x3c, 0x86, + 0xe4, 0xdc, 0x61, 0xb5, 0xd9, 0x08, 0x90, 0x75, 0xbe, 0x50, 0x8a, 0x53, 0x56, 0xac, 0x28, 0x9e, + 0x43, 0x63, 0x21, 0x90, 0x36, 0xc2, 0x55, 0xd2, 0x30, 0x1f, 0x5f, 0xda, 0xd9, 0x2e, 0x4e, 0x08, + 0xdc, 0x68, 0xb3, 0x45, 0xed, 0x8b, 0x16, 0xc3, 0xb7, 0x51, 0x21, 0x04, 0xdd, 0x72, 0xec, 0x4e, + 0xdb, 0x55, 0x32, 0xc0, 0xaa, 0xb8, 0xb3, 0x5d, 0x7c, 0x4c, 0x60, 0xb5, 0x06, 0x48, 0x71, 0x15, + 0x8c, 0x16, 0xc4, 0xdf, 0x91, 0x12, 0xb9, 0xf1, 0x11, 0x94, 0x85, 0x11, 0xf4, 0x82, 0x3f, 0x82, + 0xba, 0x0a, 0x69, 0x32, 0x5a, 0x92, 0x0f, 0xa8, 0x48, 0x33, 0x62, 0x03, 0x2a, 0x56, 0xe3, 0xc4, + 0x34, 0x3a, 0x93, 0xc8, 0x6b, 0x5f, 0x5a, 0xfd, 0x07, 0x19, 0x91, 0x4b, 0xd5, 0x36, 0x82, 0xce, + 0x5c, 0x12, 0x3b, 0xb3, 0x6a, 0x1b, 0x60, 0xea, 0xa4, 0xc2, 0x05, 0x48, 0x68, 0x6c, 0xdb, 0x36, + 0xa2, 0x16, 0x4f, 0xbc, 0x2c, 0x7e, 0x0b, 0x9d, 0x8d, 0x01, 0xd9, 0x54, 0xcb, 0xb4, 0xff, 0xf2, + 0xce, 0x76, 0x51, 0x4d, 0xe0, 0x1a, 0x9d, 0x79, 0xbb, 0x70, 0xc1, 0x3a, 0x3a, 0x27, 0x48, 0xdd, + 0xb6, 0x3c, 0xdd, 0xb4, 0xb8, 0x85, 0xc6, 0x46, 0xc9, 0x87, 0x76, 0xb6, 0x8b, 0x4f, 0x8a, 0x3a, + 0xe8, 0xd3, 0x44, 0x1b, 0xdf, 0x8d, 0x0f, 0x36, 0x90, 0x92, 0x80, 0xaa, 0xb4, 0xf4, 0x35, 0xdf, + 0xec, 0xbc, 0xb2, 0xb3, 0x5d, 0xfc, 0x40, 0x62, 0x1d, 0x26, 0xa5, 0x12, 0x97, 0xb9, 0x6e, 0x9c, + 0xb0, 0x86, 0x70, 0x88, 0x5b, 0xb4, 0x0d, 0x02, 0xdf, 0xd0, 0x0f, 0xfc, 0xd5, 0x9d, 0xed, 0xe2, + 0x25, 0x81, 0xbf, 0x65, 0x1b, 0x24, 0xda, 0xfc, 0x84, 0xd2, 0xea, 0x2f, 0x65, 0xd0, 0xa5, 0x5a, + 0x69, 0x61, 0xbe, 0x62, 0xf8, 0x76, 0x41, 0xd5, 0xb1, 0xef, 0x9b, 0x86, 0x30, 0x7a, 0x57, 0xd0, + 0xb9, 0x08, 0x6a, 0x06, 0x4c, 0x91, 0xc0, 0x22, 0x85, 0x6f, 0xf3, 0x6d, 0x8e, 0x36, 0xa7, 0xa9, + 0x33, 0x7b, 0xa5, 0x2e, 0x99, 0xe3, 0xdd, 0x18, 0xd1, 0x3e, 0x8a, 0xa0, 0x6a, 0xeb, 0xb6, 0xe3, + 0x35, 0x3a, 0x1e, 0x57, 0x02, 0xe8, 0xa3, 0x58, 0x1d, 0x2e, 0x27, 0xea, 0x51, 0x85, 0xcf, 0x07, + 0x7f, 0x2e, 0x85, 0x0a, 0x25, 0xcf, 0x73, 0xcc, 0x95, 0x8e, 0x47, 0x16, 0xf4, 0x76, 0xdb, 0xb4, + 0xd6, 0x60, 0xac, 0x0f, 0xdd, 0x78, 0x39, 0x58, 0xdf, 0x7a, 0x4a, 0x62, 0x32, 0x5a, 0x5c, 0x18, + 0xa2, 0xba, 0x8f, 0xaa, 0xb7, 0x18, 0x4e, 0x1c, 0xa2, 0xd1, 0x72, 0x74, 0x88, 0x26, 0xf2, 0xda, + 0xd7, 0x10, 0xfd, 0x52, 0x06, 0x5d, 0x58, 0xda, 0xf0, 0x74, 0x8d, 0xb8, 0x76, 0xc7, 0x69, 0x10, + 0xf7, 0x4e, 0xdb, 0xd0, 0x3d, 0x12, 0x8e, 0xd4, 0x22, 0xea, 0x2f, 0x19, 0x06, 0x31, 0x80, 0x5d, + 0x3f, 0xdb, 0x3b, 0xe9, 0x14, 0xa0, 0x31, 0x38, 0xfe, 0x20, 0x1a, 0xe0, 0x65, 0x80, 0x7b, 0xff, + 0xd4, 0xd0, 0xce, 0x76, 0x71, 0xa0, 0xc3, 0x40, 0x9a, 0x8f, 0xa3, 0x64, 0x65, 0xd2, 0x24, 0x94, + 0x2c, 0x13, 0x92, 0x19, 0x0c, 0xa4, 0xf9, 0x38, 0xfc, 0x06, 0x1a, 0x05, 0xb6, 0x41, 0x7b, 0xf8, + 0xdc, 0x77, 0xda, 0x97, 0xae, 0xd8, 0x58, 0xb6, 0x34, 0x41, 0x6b, 0xea, 0x8e, 0x5f, 0x40, 0x8b, + 0x30, 0xc0, 0xf7, 0x50, 0x81, 0x37, 0x22, 0x64, 0xda, 0xdf, 0x83, 0xe9, 0x99, 0x9d, 0xed, 0xe2, + 0x38, 0x6f, 0xbf, 0xc0, 0x36, 0xc6, 0x84, 0x32, 0xe6, 0xcd, 0x0e, 0x19, 0xe7, 0x76, 0x63, 0xcc, + 0xbf, 0x58, 0x64, 0x1c, 0x65, 0xa2, 0xbe, 0x89, 0x86, 0xc5, 0x82, 0xf8, 0x2c, 0xec, 0x4f, 0xd9, + 0x38, 0x81, 0x9d, 0xad, 0x69, 0xc0, 0xa6, 0xf4, 0x19, 0x34, 0x54, 0x26, 0x6e, 0xc3, 0x31, 0xdb, + 0xd4, 0x6a, 0xe0, 0x4a, 0x3e, 0xb6, 0xb3, 0x5d, 0x1c, 0x32, 0x42, 0xb0, 0x26, 0xd2, 0xa8, 0xff, + 0x2b, 0x85, 0xce, 0x52, 0xde, 0x25, 0xd7, 0x35, 0xd7, 0xac, 0x96, 0xb8, 0x6c, 0x5f, 0x43, 0xb9, + 0x1a, 0xd4, 0xc7, 0x6b, 0x3a, 0xbd, 0xb3, 0x5d, 0x2c, 0xb0, 0x16, 0x08, 0x7a, 0xc8, 0x69, 0x82, + 0xcd, 0x59, 0x7a, 0x97, 0xcd, 0x19, 0x35, 0x47, 0x3d, 0xdd, 0xf1, 0x4c, 0x6b, 0xad, 0xe6, 0xe9, + 0x5e, 0xc7, 0x95, 0xcc, 0x51, 0x8e, 0xa9, 0xbb, 0x80, 0x92, 0xcc, 0x51, 0xa9, 0x10, 0x7e, 0x15, + 0x0d, 0xcf, 0x58, 0x46, 0xc8, 0x84, 0x4d, 0x88, 0x8f, 0x51, 0x2b, 0x91, 0x00, 0x3c, 0xce, 0x42, + 0x2a, 0xa0, 0xfe, 0xfd, 0x14, 0x52, 0xd8, 0x4e, 0x6a, 0xde, 0x74, 0xbd, 0x05, 0xd2, 0x5a, 0x11, + 0x66, 0xa7, 0x59, 0x7f, 0x6b, 0x46, 0x71, 0xc2, 0x5a, 0x04, 0xa6, 0x00, 0xdf, 0x9a, 0x35, 0x4d, + 0xd7, 0x8b, 0x4e, 0x86, 0x91, 0x52, 0xb8, 0x82, 0x06, 0x18, 0x67, 0x66, 0x4b, 0x0c, 0xdd, 0x50, + 0x7c, 0x45, 0x88, 0x56, 0xcd, 0x94, 0xa1, 0xc5, 0x88, 0xc5, 0xbd, 0x35, 0x2f, 0xaf, 0xfe, 0x83, + 0x34, 0x2a, 0x44, 0x0b, 0xe1, 0x7b, 0x28, 0xff, 0xba, 0x6d, 0x5a, 0xc4, 0x58, 0xb2, 0xa0, 0x85, + 0xbd, 0x4f, 0x18, 0x7c, 0x3b, 0xfa, 0xd4, 0xdb, 0x50, 0xa6, 0x6e, 0x0b, 0x3b, 0x53, 0x38, 0x70, + 0x08, 0x98, 0xe1, 0x4f, 0xa2, 0x41, 0x6a, 0x03, 0xde, 0x07, 0xce, 0xe9, 0x5d, 0x39, 0x3f, 0xce, + 0x39, 0x9f, 0x76, 0x58, 0xa1, 0x38, 0xeb, 0x90, 0x1d, 0xd5, 0x2b, 0x8d, 0xe8, 0xae, 0x6d, 0xf1, + 0x9e, 0x07, 0xbd, 0x72, 0x00, 0x22, 0xea, 0x15, 0xa3, 0xa1, 0xa6, 0x2b, 0xfb, 0x58, 0xe8, 0x06, + 0x61, 0xdf, 0xc1, 0x64, 0x15, 0xed, 0x01, 0x81, 0x58, 0xfd, 0xae, 0x34, 0x7a, 0x3a, 0x14, 0x99, + 0x46, 0xee, 0x9b, 0x64, 0x93, 0x8b, 0x73, 0xdd, 0x6c, 0xf3, 0x8d, 0x1f, 0x55, 0x79, 0x77, 0x7a, + 0x5d, 0xb7, 0xd6, 0x88, 0x81, 0xaf, 0xa2, 0x7e, 0xba, 0x3b, 0x77, 0x95, 0x14, 0x98, 0x6b, 0x30, + 0x9d, 0xd0, 0x5d, 0xbc, 0xd8, 0x23, 0x8c, 0x02, 0xdb, 0x28, 0xb7, 0xec, 0xe8, 0xa6, 0xe7, 0xf7, + 0x6c, 0x29, 0xde, 0xb3, 0x7b, 0xa8, 0x71, 0x92, 0xf1, 0x60, 0x73, 0x3e, 0x08, 0xc2, 0x03, 0x80, + 0x28, 0x08, 0x46, 0x32, 0xf1, 0x22, 0x1a, 0x12, 0x88, 0xf7, 0x35, 0xa9, 0x7f, 0x39, 0x2b, 0xea, + 0xba, 0xdf, 0x2c, 0xae, 0xeb, 0xd7, 0xa9, 0x8e, 0xba, 0x2e, 0xb5, 0x2a, 0x98, 0x92, 0x73, 0x4d, + 0x04, 0x90, 0xac, 0x89, 0x00, 0xc2, 0xcf, 0xa2, 0x3c, 0x63, 0x11, 0xec, 0x3d, 0x61, 0xdf, 0xea, + 0x00, 0x4c, 0x5e, 0x9a, 0x03, 0x42, 0xfc, 0x53, 0x29, 0x74, 0xb1, 0xa7, 0x24, 0x40, 0x19, 0x86, + 0x6e, 0x3c, 0x77, 0x20, 0x31, 0x4e, 0x3d, 0xbd, 0xb3, 0x5d, 0xbc, 0xda, 0x0a, 0x48, 0xea, 0x8e, + 0x40, 0x53, 0x6f, 0x30, 0x22, 0xa1, 0x5d, 0xbd, 0x9b, 0x42, 0x8d, 0x47, 0x56, 0xe9, 0x2c, 0x9c, + 0xbf, 0x58, 0x8d, 0x2d, 0xbf, 0x91, 0xd9, 0xd0, 0x78, 0xe4, 0xdf, 0xbb, 0xea, 0x93, 0x24, 0x54, + 0xd3, 0x85, 0x0b, 0x6e, 0xa0, 0x73, 0x0c, 0x53, 0xd6, 0xb7, 0x96, 0x56, 0x17, 0x6c, 0xcb, 0x5b, + 0xf7, 0x2b, 0xe8, 0x17, 0x0f, 0x30, 0xa0, 0x02, 0x43, 0xdf, 0xaa, 0xdb, 0xab, 0xf5, 0x16, 0xa5, + 0x4a, 0xa8, 0xa3, 0x1b, 0x27, 0x3a, 0xd1, 0xf2, 0x31, 0xe7, 0x4f, 0x41, 0xb9, 0xf0, 0x78, 0xc9, + 0x1f, 0xa7, 0xf1, 0x09, 0x27, 0x52, 0x48, 0xad, 0xa0, 0xe1, 0x79, 0xbb, 0xb1, 0x11, 0xa8, 0xcb, + 0x8b, 0x28, 0xb7, 0xac, 0x3b, 0x6b, 0xc4, 0x03, 0x59, 0x0c, 0xdd, 0x18, 0x9f, 0x64, 0x47, 0xb6, + 0x94, 0x88, 0x21, 0xa6, 0x46, 0xf9, 0x6c, 0x90, 0xf3, 0xe0, 0xb7, 0xc6, 0x0b, 0xa8, 0x5f, 0xef, + 0x47, 0xc3, 0xfc, 0x78, 0x11, 0x66, 0x73, 0xfc, 0x52, 0x78, 0x60, 0xcb, 0xa7, 0xaf, 0xe0, 0x88, + 0x25, 0x38, 0x1a, 0x1a, 0xa6, 0xcc, 0x7e, 0x73, 0xbb, 0x98, 0xda, 0xd9, 0x2e, 0xf6, 0x69, 0x79, + 0x61, 0x53, 0x19, 0xae, 0x37, 0xc2, 0x02, 0x2b, 0x1e, 0x18, 0x46, 0xca, 0xb2, 0xf5, 0xe7, 0x55, + 0x34, 0xc0, 0xdb, 0xc0, 0x35, 0xee, 0x5c, 0x78, 0x0e, 0x21, 0x1d, 0x93, 0x46, 0x4a, 0xfb, 0xa5, + 0xf0, 0xcb, 0x28, 0xc7, 0xf6, 0xf6, 0x5c, 0x00, 0x67, 0x93, 0xcf, 0x31, 0x22, 0xc5, 0x79, 0x19, + 0x3c, 0x87, 0x50, 0xb8, 0xaf, 0x0f, 0x4e, 0x85, 0x39, 0x87, 0xf8, 0x8e, 0x3f, 0xc2, 0x45, 0x28, + 0x8b, 0x9f, 0x47, 0xc3, 0xcb, 0xc4, 0x69, 0x99, 0x96, 0xde, 0xac, 0x99, 0xef, 0xf8, 0x07, 0xc3, + 0xb0, 0xf0, 0xba, 0xe6, 0x3b, 0xe2, 0xc8, 0x95, 0xe8, 0xf0, 0xa7, 0x93, 0xf6, 0xcd, 0x03, 0xd0, + 0x90, 0x27, 0x76, 0xdd, 0x50, 0x46, 0xda, 0x93, 0xb0, 0x8d, 0x7e, 0x03, 0x8d, 0x48, 0x5b, 0x26, + 0x7e, 0xf2, 0x77, 0x31, 0xce, 0x5a, 0xd8, 0xff, 0x45, 0xd8, 0xca, 0x1c, 0xa8, 0x26, 0x57, 0x2c, + 0xd3, 0x33, 0xf5, 0xe6, 0xb4, 0xdd, 0x6a, 0xe9, 0x96, 0xa1, 0x0c, 0x86, 0x9a, 0x6c, 0x32, 0x4c, + 0xbd, 0xc1, 0x50, 0xa2, 0x26, 0xcb, 0x85, 0xe8, 0xb6, 0x9c, 0xf7, 0xa1, 0x46, 0x1a, 0xb6, 0x43, + 0x6d, 0x01, 0x38, 0xd8, 0xe3, 0xdb, 0x72, 0x97, 0xe1, 0xea, 0x8e, 0x8f, 0x14, 0x8d, 0xed, 0x68, + 0xc1, 0xd7, 0xb3, 0xf9, 0xa1, 0xc2, 0x70, 0xf4, 0x2c, 0x56, 0xfd, 0x7b, 0x19, 0x34, 0xc4, 0x49, + 0xe9, 0x52, 0x7a, 0xa2, 0xe0, 0x87, 0x51, 0xf0, 0x44, 0x45, 0xcd, 0x3d, 0x2c, 0x45, 0x55, 0x3f, + 0x9f, 0x0e, 0x66, 0xa3, 0xaa, 0x63, 0x5a, 0x87, 0x9b, 0x8d, 0x2e, 0x23, 0x34, 0xbd, 0xde, 0xb1, + 0x36, 0xd8, 0x9d, 0x53, 0x3a, 0xbc, 0x73, 0x6a, 0x98, 0x9a, 0x80, 0xc1, 0x17, 0x51, 0xb6, 0x4c, + 0xf9, 0xd3, 0x9e, 0x19, 0x9e, 0x1a, 0x7c, 0x97, 0x71, 0x4a, 0x3d, 0xad, 0x01, 0x98, 0x6e, 0xae, + 0xa6, 0xb6, 0x3c, 0xc2, 0xcc, 0xd9, 0x0c, 0xdb, 0x5c, 0xad, 0x50, 0x80, 0xc6, 0xe0, 0xf8, 0x26, + 0x1a, 0x2f, 0x93, 0xa6, 0xbe, 0xb5, 0x60, 0x36, 0x9b, 0xa6, 0x4b, 0x1a, 0xb6, 0x65, 0xb8, 0x20, + 0x64, 0x5e, 0x5d, 0xcb, 0xd5, 0xe2, 0x04, 0x58, 0x45, 0xb9, 0xa5, 0xd5, 0x55, 0x97, 0x78, 0x20, + 0xbe, 0xcc, 0x14, 0xa2, 0x93, 0xb3, 0x0d, 0x10, 0x8d, 0x63, 0xd4, 0x9f, 0x4d, 0xd1, 0xdd, 0x8b, + 0xbb, 0xe1, 0xd9, 0xed, 0x40, 0xcb, 0x0f, 0x25, 0x92, 0xab, 0xa1, 0x5d, 0x91, 0x86, 0xaf, 0x1d, + 0xe3, 0x5f, 0x3b, 0xc0, 0x6d, 0x8b, 0xd0, 0xa2, 0x48, 0xfc, 0xaa, 0xcc, 0x2e, 0x5f, 0xa5, 0xfe, + 0x61, 0x1a, 0x9d, 0xe3, 0x2d, 0x9e, 0x6e, 0x9a, 0xed, 0x15, 0x5b, 0x77, 0x0c, 0x8d, 0x34, 0x88, + 0x79, 0x9f, 0x1c, 0xcf, 0x81, 0x27, 0x0f, 0x9d, 0xec, 0x21, 0x86, 0xce, 0x0d, 0xd8, 0x08, 0x52, + 0xc9, 0xc0, 0x81, 0x2f, 0x33, 0x2a, 0x0a, 0x3b, 0xdb, 0xc5, 0x61, 0x83, 0x81, 0xe1, 0xb8, 0x5e, + 0x13, 0x89, 0xa8, 0x92, 0xcc, 0x13, 0x6b, 0xcd, 0x5b, 0x07, 0x25, 0xe9, 0x67, 0x4a, 0xd2, 0x04, + 0x88, 0xc6, 0x31, 0xea, 0xff, 0x48, 0xa3, 0xd3, 0x51, 0x91, 0xd7, 0x88, 0x65, 0x9c, 0xc8, 0xfb, + 0x9b, 0x23, 0xef, 0x6f, 0x64, 0xd0, 0x63, 0xbc, 0x4c, 0x6d, 0x5d, 0x77, 0x88, 0x51, 0x36, 0x1d, + 0xd2, 0xf0, 0x6c, 0x67, 0xeb, 0x18, 0x1b, 0x50, 0x0f, 0x4f, 0xec, 0x37, 0x51, 0x8e, 0x6f, 0xff, + 0xd9, 0x3a, 0x33, 0x1a, 0xb4, 0x04, 0xa0, 0xb1, 0x15, 0x8a, 0x1d, 0x1d, 0x44, 0x3a, 0x2b, 0xb7, + 0x97, 0xce, 0xfa, 0x28, 0x1a, 0x09, 0x44, 0x0f, 0x1b, 0xd1, 0x81, 0xd0, 0xda, 0x32, 0x7c, 0x04, + 0xec, 0x45, 0x35, 0x99, 0x10, 0x6a, 0xf3, 0x01, 0x95, 0x32, 0x58, 0x43, 0x23, 0xbc, 0xb6, 0xa0, + 0x9c, 0x69, 0x68, 0x22, 0x91, 0xba, 0x9d, 0x45, 0x13, 0xc9, 0xdd, 0xae, 0x11, 0xdd, 0x38, 0xe9, + 0xf5, 0xf7, 0x65, 0xaf, 0xe3, 0x27, 0x50, 0xb6, 0xaa, 0x7b, 0xeb, 0xfc, 0x0e, 0x1b, 0xee, 0x73, + 0x57, 0xcd, 0x26, 0xa9, 0xb7, 0x75, 0x6f, 0x5d, 0x03, 0x94, 0x30, 0x67, 0x20, 0xe0, 0x98, 0x30, + 0x67, 0x08, 0x8b, 0xfd, 0xd0, 0xe3, 0xa9, 0x2b, 0xd9, 0xc4, 0xc5, 0xfe, 0xeb, 0xd9, 0x6e, 0xf3, + 0xca, 0x3d, 0xc7, 0xf4, 0xc8, 0x89, 0x86, 0x9d, 0x68, 0xd8, 0x21, 0x35, 0xec, 0xb7, 0xd3, 0x68, + 0x24, 0xd8, 0x34, 0xbd, 0x4d, 0x1a, 0x47, 0xb3, 0x56, 0x85, 0x5b, 0x99, 0xcc, 0xa1, 0xb7, 0x32, + 0x87, 0x51, 0x28, 0x35, 0x38, 0xf2, 0x64, 0xa6, 0x01, 0x48, 0x8c, 0x1d, 0x79, 0x06, 0x07, 0x9d, + 0x4f, 0xa0, 0x81, 0x05, 0xfd, 0x81, 0xd9, 0xea, 0xb4, 0xb8, 0x95, 0x0e, 0x3e, 0x59, 0x2d, 0xfd, + 0x81, 0xe6, 0xc3, 0xd5, 0x7f, 0x9b, 0x42, 0xa3, 0x5c, 0xa8, 0x9c, 0xf9, 0xa1, 0xa4, 0x1a, 0x4a, + 0x27, 0x7d, 0x68, 0xe9, 0x64, 0x0e, 0x2e, 0x1d, 0xf5, 0xc7, 0x32, 0x48, 0x99, 0x35, 0x9b, 0x64, + 0xd9, 0xd1, 0x2d, 0x77, 0x95, 0x38, 0x7c, 0x3b, 0x3d, 0x43, 0x59, 0x1d, 0xea, 0x03, 0x85, 0x29, + 0x25, 0x7d, 0xa0, 0x29, 0xe5, 0xc3, 0x68, 0x90, 0x37, 0x26, 0xf0, 0x07, 0x84, 0x51, 0xe3, 0xf8, + 0x40, 0x2d, 0xc4, 0x53, 0xe2, 0x52, 0xbb, 0xed, 0xd8, 0xf7, 0x89, 0xc3, 0x6e, 0xa9, 0x38, 0xb1, + 0xee, 0x03, 0xb5, 0x10, 0x2f, 0x70, 0x26, 0xbe, 0xbd, 0x28, 0x72, 0x26, 0x8e, 0x16, 0xe2, 0xf1, + 0x15, 0x94, 0x9f, 0xb7, 0x1b, 0x3a, 0x08, 0x9a, 0x4d, 0x2b, 0xc3, 0x3b, 0xdb, 0xc5, 0x7c, 0x93, + 0xc3, 0xb4, 0x00, 0x4b, 0x29, 0xcb, 0xf6, 0xa6, 0xd5, 0xb4, 0x75, 0xe6, 0xb8, 0x92, 0x67, 0x94, + 0x06, 0x87, 0x69, 0x01, 0x96, 0x52, 0x52, 0x99, 0x83, 0x43, 0x50, 0x3e, 0xe4, 0xb9, 0xca, 0x61, + 0x5a, 0x80, 0x55, 0x7f, 0x36, 0x4b, 0xb5, 0xd7, 0x35, 0xdf, 0x79, 0xe4, 0xd7, 0x85, 0x70, 0xc0, + 0xf4, 0x1f, 0x60, 0xc0, 0x3c, 0x32, 0x07, 0x76, 0xea, 0xff, 0x1e, 0x40, 0x88, 0x4b, 0x7f, 0xe6, + 0x64, 0x73, 0x78, 0x38, 0xad, 0x29, 0xa3, 0xf1, 0x19, 0x6b, 0x5d, 0xb7, 0x1a, 0xc4, 0x08, 0x8f, + 0x2d, 0x73, 0x30, 0xb4, 0xc1, 0x1f, 0x97, 0x70, 0x64, 0x78, 0x6e, 0xa9, 0xc5, 0x0b, 0xe0, 0x67, + 0xd0, 0x50, 0xc5, 0xf2, 0x88, 0xa3, 0x37, 0x3c, 0xf3, 0x3e, 0xe1, 0x53, 0x03, 0xdc, 0x0c, 0x9b, + 0x21, 0x58, 0x13, 0x69, 0xf0, 0x4d, 0x34, 0x5c, 0xd5, 0x1d, 0xcf, 0x6c, 0x98, 0x6d, 0xdd, 0xf2, + 0x5c, 0x25, 0x0f, 0x33, 0x1a, 0x58, 0x18, 0x6d, 0x01, 0xae, 0x49, 0x54, 0xf8, 0xd3, 0x68, 0x10, + 0xb6, 0xa6, 0xe0, 0xf4, 0x3c, 0xb8, 0xeb, 0xc5, 0xe1, 0x93, 0xa1, 0x6b, 0x1f, 0x3b, 0x7d, 0x85, + 0x1b, 0xe0, 0xe8, 0xdd, 0x61, 0xc0, 0x11, 0x7f, 0x02, 0x0d, 0xcc, 0x58, 0x06, 0x30, 0x47, 0xbb, + 0x32, 0x57, 0x39, 0xf3, 0xb3, 0x21, 0x73, 0xbb, 0x1d, 0xe1, 0xed, 0xb3, 0x4b, 0x1e, 0x65, 0x43, + 0xdf, 0xbc, 0x51, 0x36, 0xfc, 0x4d, 0x38, 0x16, 0x1f, 0x79, 0x58, 0xc7, 0xe2, 0xa3, 0x07, 0x3c, + 0x16, 0x57, 0xdf, 0x41, 0x43, 0x53, 0xd5, 0xd9, 0x60, 0xf4, 0x9e, 0x47, 0x99, 0x2a, 0xf7, 0x54, + 0xc8, 0x32, 0x7b, 0xa6, 0x6d, 0x1a, 0x1a, 0x85, 0xe1, 0xab, 0x28, 0x3f, 0x0d, 0xee, 0x6f, 0xfc, + 0x16, 0x31, 0xcb, 0xd6, 0xbf, 0x06, 0xc0, 0xc0, 0x83, 0xd5, 0x47, 0xe3, 0x0f, 0xa2, 0x81, 0xaa, + 0x63, 0xaf, 0x39, 0x7a, 0x8b, 0xaf, 0xc1, 0xe0, 0x2a, 0xd2, 0x66, 0x20, 0xcd, 0xc7, 0xa9, 0xdf, + 0x9f, 0xf2, 0xcd, 0x76, 0x5a, 0xa2, 0xd6, 0x81, 0xa3, 0x79, 0xa8, 0x3b, 0xcf, 0x4a, 0xb8, 0x0c, + 0xa4, 0xf9, 0x38, 0x7c, 0x15, 0xf5, 0xcf, 0x38, 0x8e, 0xed, 0x88, 0x8e, 0xe2, 0x84, 0x02, 0xc4, + 0xeb, 0x5e, 0xa0, 0xc0, 0x2f, 0xa0, 0x21, 0x36, 0xe7, 0xb0, 0x13, 0xcd, 0x4c, 0xaf, 0x9b, 0x52, + 0x91, 0x52, 0xfd, 0x6a, 0x46, 0xb0, 0xd9, 0x98, 0xc4, 0x1f, 0xc1, 0x5b, 0x81, 0x67, 0x51, 0x66, + 0xaa, 0x3a, 0xcb, 0x27, 0xc0, 0x53, 0x7e, 0x51, 0x41, 0x55, 0x22, 0xe5, 0x28, 0x35, 0xbe, 0x80, + 0xb2, 0x55, 0xaa, 0x3e, 0x39, 0x50, 0x8f, 0xfc, 0xce, 0x76, 0x31, 0xdb, 0xa6, 0xfa, 0x03, 0x50, + 0xc0, 0xd2, 0xcd, 0x0c, 0xdb, 0x31, 0x31, 0x6c, 0xb8, 0x8f, 0xb9, 0x80, 0xb2, 0x25, 0x67, 0xed, + 0x3e, 0x9f, 0xb5, 0x00, 0xab, 0x3b, 0x6b, 0xf7, 0x35, 0x80, 0xe2, 0xeb, 0x08, 0x69, 0xc4, 0xeb, + 0x38, 0x16, 0xbc, 0xe1, 0x18, 0x84, 0xf3, 0x37, 0x98, 0x0d, 0x1d, 0x80, 0xd6, 0x1b, 0xb6, 0x41, + 0x34, 0x81, 0x44, 0xfd, 0xbb, 0xe1, 0xc5, 0x4e, 0xd9, 0x74, 0x37, 0x4e, 0xba, 0x70, 0x1f, 0x5d, + 0xa8, 0xf3, 0x23, 0xce, 0x78, 0x27, 0x15, 0x51, 0xff, 0x6c, 0x53, 0x5f, 0x73, 0xa1, 0x0f, 0xb9, + 0x2f, 0xd9, 0x2a, 0x05, 0x68, 0x0c, 0x1e, 0xe9, 0xa7, 0xfc, 0xee, 0xfd, 0xf4, 0x43, 0xfd, 0xc1, + 0x68, 0x5b, 0x24, 0xde, 0xa6, 0xed, 0x9c, 0x74, 0xd5, 0x5e, 0xbb, 0xea, 0x32, 0x1a, 0xa8, 0x39, + 0x0d, 0xe1, 0xe8, 0x02, 0xf6, 0x03, 0xae, 0xd3, 0x60, 0xc7, 0x16, 0x3e, 0x92, 0xd2, 0x95, 0x5d, + 0x0f, 0xe8, 0x06, 0x42, 0x3a, 0xc3, 0xf5, 0x38, 0x1d, 0x47, 0x72, 0xba, 0xaa, 0xed, 0x78, 0xbc, + 0xe3, 0x02, 0xba, 0xb6, 0xed, 0x78, 0x9a, 0x8f, 0xc4, 0x1f, 0x46, 0x68, 0x79, 0xba, 0x7a, 0x97, + 0x38, 0x20, 0xae, 0xc1, 0xd0, 0x17, 0xf0, 0x3e, 0x03, 0x69, 0x02, 0x1a, 0x2f, 0xa3, 0xc1, 0xa5, + 0x36, 0x71, 0xd8, 0x56, 0x88, 0xbd, 0xca, 0xf8, 0x50, 0x44, 0xb4, 0xbc, 0xdf, 0x27, 0xf9, 0xff, + 0x01, 0x39, 0x5b, 0x5f, 0x6c, 0xff, 0xa7, 0x16, 0x32, 0xc2, 0x2f, 0xa0, 0x5c, 0x89, 0xd9, 0x79, + 0x43, 0xc0, 0x32, 0x10, 0x19, 0x6c, 0x41, 0x19, 0x8a, 0xed, 0xd9, 0x75, 0xf8, 0x5b, 0xe3, 0xe4, + 0xea, 0x55, 0x54, 0x88, 0x56, 0x83, 0x87, 0xd0, 0xc0, 0xf4, 0xd2, 0xe2, 0xe2, 0xcc, 0xf4, 0x72, + 0xa1, 0x0f, 0xe7, 0x51, 0xb6, 0x36, 0xb3, 0x58, 0x2e, 0xa4, 0xd4, 0x9f, 0x16, 0x66, 0x10, 0xaa, + 0x5a, 0x27, 0x57, 0xc3, 0x87, 0xba, 0x6f, 0x29, 0xc0, 0x7d, 0x28, 0x9c, 0x18, 0xb4, 0x4c, 0xcf, + 0x23, 0x06, 0x5f, 0x25, 0xe0, 0xbe, 0xd0, 0x7b, 0xa0, 0xc5, 0xf0, 0xf8, 0x1a, 0x1a, 0x01, 0x18, + 0xbf, 0x22, 0x64, 0xfb, 0x63, 0x5e, 0xc0, 0x79, 0xa0, 0xc9, 0x48, 0xf5, 0x6b, 0xe1, 0xed, 0xf0, + 0x3c, 0xd1, 0x8f, 0xeb, 0x8d, 0xe2, 0x7b, 0xa4, 0xbf, 0xd4, 0x3f, 0xc9, 0xb2, 0x27, 0x20, 0xec, + 0xd1, 0xdd, 0x51, 0x88, 0x32, 0x3c, 0xd2, 0xcd, 0xec, 0xe3, 0x48, 0xf7, 0x1a, 0xca, 0x2d, 0x10, + 0x6f, 0xdd, 0xf6, 0x1d, 0xbf, 0xc0, 0x43, 0xaf, 0x05, 0x10, 0xd1, 0x43, 0x8f, 0xd1, 0xe0, 0x0d, + 0x84, 0xfd, 0x17, 0x75, 0x81, 0x23, 0xb6, 0x7f, 0x84, 0x7c, 0x2e, 0xb6, 0x4f, 0xa9, 0xc1, 0x73, + 0x5a, 0xf0, 0xb1, 0x3f, 0x1d, 0x38, 0x7a, 0x0b, 0x9e, 0x58, 0x7f, 0xbc, 0x5d, 0xcc, 0x31, 0x1a, + 0x2d, 0x81, 0x2d, 0x7e, 0x03, 0x0d, 0x2e, 0xcc, 0x96, 0xf8, 0xeb, 0x3a, 0xe6, 0x15, 0x71, 0x3e, + 0x90, 0xa2, 0x8f, 0x08, 0x44, 0x02, 0xef, 0x6d, 0x5a, 0xab, 0x7a, 0xfc, 0x71, 0x5d, 0xc8, 0x85, + 0x6a, 0x0b, 0x7b, 0xb9, 0xc3, 0x4f, 0x17, 0x02, 0x6d, 0x91, 0xdf, 0xf3, 0x44, 0x65, 0xc5, 0xb0, + 0x11, 0x6d, 0xc9, 0x1f, 0x62, 0x74, 0x2f, 0xa1, 0xf1, 0x52, 0xbb, 0xdd, 0x34, 0x89, 0x01, 0xfa, + 0xa2, 0x75, 0x9a, 0xc4, 0xe5, 0x2e, 0x3f, 0xf0, 0x18, 0x44, 0x67, 0xc8, 0x3a, 0xbc, 0xe9, 0xac, + 0x3b, 0x1d, 0xd9, 0x3f, 0x33, 0x5e, 0x56, 0xfd, 0xc1, 0x34, 0x3a, 0x3b, 0xed, 0x10, 0xdd, 0x23, + 0x0b, 0xb3, 0xa5, 0x52, 0x07, 0x7c, 0xe4, 0x9a, 0x4d, 0x62, 0xad, 0x1d, 0xcd, 0xb0, 0xfe, 0x18, + 0x1a, 0x0d, 0x1a, 0x50, 0x6b, 0xd8, 0x6d, 0x22, 0x3e, 0xac, 0x6a, 0xf8, 0x98, 0xba, 0x4b, 0x51, + 0x5a, 0x84, 0x14, 0xdf, 0x46, 0xa7, 0x02, 0x48, 0xa9, 0xd9, 0xb4, 0x37, 0x35, 0xd2, 0x71, 0x99, + 0x63, 0x6c, 0x9e, 0x39, 0xc6, 0x86, 0x1c, 0x74, 0x8a, 0xaf, 0x3b, 0x94, 0x40, 0x4b, 0x2a, 0xa5, + 0xfe, 0x78, 0x06, 0x9d, 0xbb, 0xab, 0x37, 0x4d, 0x23, 0x14, 0x8d, 0x46, 0xdc, 0xb6, 0x6d, 0xb9, + 0xe4, 0x18, 0x8d, 0x52, 0x69, 0x28, 0x64, 0x1f, 0xca, 0x50, 0x88, 0x77, 0x51, 0xff, 0xa1, 0xbb, + 0x28, 0x77, 0xa0, 0x2e, 0xfa, 0xef, 0x29, 0x54, 0xf0, 0x1d, 0xff, 0xc5, 0x97, 0xd0, 0x82, 0x57, + 0x3a, 0x1c, 0x21, 0x46, 0xfc, 0xa0, 0x01, 0x8f, 0x6b, 0x68, 0x60, 0xe6, 0x41, 0xdb, 0x74, 0x88, + 0xbb, 0x07, 0x27, 0xee, 0x8b, 0xfc, 0xb8, 0x64, 0x9c, 0xb0, 0x22, 0xb1, 0x93, 0x12, 0x06, 0x86, + 0xe7, 0x7c, 0xec, 0xe9, 0xc3, 0x94, 0xff, 0xbc, 0x9b, 0x3d, 0xe7, 0xe3, 0x4f, 0x24, 0xa4, 0xb7, + 0x95, 0x21, 0x29, 0x7e, 0x12, 0x65, 0x96, 0x97, 0xe7, 0xf9, 0x4c, 0x0a, 0xcf, 0xea, 0x3d, 0x4f, + 0x7c, 0xaf, 0x48, 0xb1, 0xea, 0xef, 0xa6, 0x11, 0xa2, 0xaa, 0xc0, 0x86, 0xeb, 0x91, 0x28, 0xe1, + 0x14, 0xca, 0xfb, 0x02, 0xe7, 0x6a, 0x18, 0x78, 0xed, 0x47, 0x3b, 0x22, 0x5a, 0x77, 0xf0, 0x42, + 0xa3, 0xe8, 0x3b, 0x92, 0xb3, 0x7b, 0x00, 0xd8, 0xd9, 0x80, 0x23, 0xb9, 0xef, 0x3e, 0xfe, 0x61, + 0x34, 0xc8, 0x67, 0x3c, 0x5b, 0x3a, 0xff, 0x6f, 0xf8, 0x40, 0x2d, 0xc4, 0x47, 0xa6, 0xd6, 0xdc, + 0x21, 0x16, 0x62, 0x5f, 0xbc, 0xac, 0x57, 0x4e, 0xc4, 0xfb, 0x90, 0xc5, 0xfb, 0x05, 0x2e, 0x5e, + 0xf6, 0x82, 0xe7, 0xd8, 0x8a, 0xf7, 0xa1, 0x9d, 0x7d, 0xab, 0xbf, 0x9d, 0x42, 0x98, 0x36, 0xab, + 0xaa, 0xbb, 0xee, 0xa6, 0xed, 0x18, 0xcc, 0x39, 0xfd, 0x48, 0x04, 0xf3, 0xf0, 0xee, 0x2b, 0xbf, + 0x9a, 0x47, 0xa7, 0x24, 0xc7, 0xdf, 0x63, 0x3e, 0x59, 0x5d, 0x95, 0x47, 0x53, 0xaf, 0x57, 0x2f, + 0x1f, 0x10, 0x2f, 0x44, 0xfb, 0xa5, 0x07, 0x68, 0xc2, 0x4d, 0xe8, 0xd3, 0x68, 0x98, 0xff, 0xa0, + 0x2b, 0xb4, 0x7f, 0xd3, 0x05, 0xa3, 0xd4, 0xa5, 0x00, 0x4d, 0x42, 0xe3, 0xe7, 0xd0, 0x20, 0x1d, + 0x30, 0x6b, 0x10, 0x81, 0x63, 0x20, 0x7c, 0x51, 0x62, 0xf8, 0x40, 0x71, 0x3d, 0x09, 0x28, 0x85, + 0x77, 0x44, 0xf9, 0x3d, 0xbc, 0x23, 0x7a, 0x0b, 0x0d, 0x95, 0x2c, 0xcb, 0xf6, 0x60, 0x93, 0xee, + 0xf2, 0xab, 0x89, 0xae, 0x56, 0xf9, 0x93, 0xf0, 0x38, 0x3e, 0xa4, 0x4f, 0x34, 0xcb, 0x45, 0x86, + 0xf8, 0x86, 0xff, 0x2a, 0x86, 0x38, 0xdc, 0xab, 0x1c, 0xae, 0x67, 0x1c, 0x0e, 0x8b, 0x3f, 0x8a, + 0x81, 0xce, 0x1b, 0xa9, 0x3a, 0x76, 0xdb, 0x76, 0x89, 0xc1, 0x04, 0x35, 0x14, 0x86, 0xee, 0x68, + 0x73, 0x04, 0xbc, 0x63, 0x93, 0xa2, 0x61, 0x48, 0x45, 0xf0, 0x2a, 0x3a, 0xed, 0x5f, 0x14, 0x07, + 0x2f, 0x06, 0x2b, 0x65, 0x57, 0x19, 0x86, 0x57, 0x49, 0x38, 0xaa, 0x0c, 0x95, 0xf2, 0xd4, 0x25, + 0xff, 0x5a, 0xc4, 0x7f, 0x72, 0x58, 0x37, 0x0d, 0xb1, 0xab, 0x13, 0xf9, 0xe1, 0x6f, 0x45, 0x43, + 0x0b, 0xfa, 0x83, 0x72, 0x87, 0x9f, 0xbd, 0x8c, 0xec, 0xfd, 0xf6, 0xa5, 0xa5, 0x3f, 0xa8, 0x1b, + 0xbc, 0x5c, 0xc4, 0xa6, 0x10, 0x59, 0xe2, 0x3a, 0x3a, 0x5b, 0x75, 0xec, 0x96, 0xed, 0x11, 0x23, + 0xf2, 0xf8, 0x6e, 0x2c, 0x7c, 0xad, 0xdb, 0xe6, 0x14, 0xf5, 0x1e, 0xaf, 0xf0, 0xba, 0xb0, 0xc1, + 0x2d, 0x34, 0x56, 0x72, 0xdd, 0x4e, 0x8b, 0x84, 0x37, 0x54, 0x85, 0x5d, 0x3f, 0xe3, 0x43, 0xdc, + 0x6b, 0xf9, 0x31, 0x1d, 0x8a, 0xb2, 0x0b, 0xaa, 0xba, 0x67, 0x8a, 0x35, 0xc2, 0xb7, 0x44, 0x79, + 0xbf, 0x9e, 0xcd, 0x8f, 0x16, 0xc6, 0xb4, 0x73, 0xf1, 0xc6, 0x2c, 0x9b, 0x5e, 0x93, 0xa8, 0x5f, + 0x49, 0x21, 0x14, 0x0a, 0x18, 0x3f, 0x2d, 0x87, 0xf9, 0x49, 0x85, 0x17, 0x1d, 0x3c, 0x7a, 0x81, + 0x14, 0xd7, 0x07, 0x5f, 0x40, 0x59, 0x88, 0x4e, 0x91, 0x0e, 0x0f, 0x56, 0x37, 0x4c, 0xcb, 0xd0, + 0x00, 0x4a, 0xb1, 0xc2, 0x53, 0x74, 0xc0, 0xc2, 0xa5, 0x3e, 0xb3, 0x0a, 0xcb, 0x68, 0xac, 0xd6, + 0x59, 0xf1, 0xeb, 0x16, 0xde, 0xd5, 0x41, 0x90, 0x0c, 0xb7, 0xb3, 0x12, 0x3c, 0x46, 0x95, 0x42, + 0x90, 0xc8, 0x45, 0xd4, 0x9f, 0x4d, 0x45, 0x66, 0xc1, 0x23, 0x5c, 0xf4, 0x3e, 0x10, 0xf7, 0xd3, + 0x88, 0x4f, 0x4b, 0xea, 0xdf, 0x4a, 0xa3, 0xa1, 0xaa, 0xed, 0x78, 0x3c, 0xdc, 0xc7, 0xf1, 0x5e, + 0x85, 0x84, 0xbd, 0x52, 0x76, 0x1f, 0x7b, 0xa5, 0x0b, 0x28, 0x2b, 0xb8, 0x28, 0xb3, 0x7b, 0x11, + 0xc3, 0x70, 0x34, 0x80, 0xaa, 0xdf, 0x96, 0x46, 0xe8, 0x13, 0xcf, 0x3c, 0xf3, 0x08, 0x0b, 0x48, + 0xfd, 0xd1, 0x14, 0x1a, 0xe3, 0x17, 0x75, 0x42, 0xc0, 0xac, 0x01, 0xff, 0x8a, 0x55, 0x1c, 0x97, + 0x0c, 0xa4, 0xf9, 0x38, 0xba, 0x04, 0xcc, 0x3c, 0x30, 0x3d, 0xb8, 0xab, 0x10, 0x22, 0x66, 0x11, + 0x0e, 0x13, 0x97, 0x00, 0x9f, 0x0e, 0x3f, 0xed, 0x5f, 0x41, 0x66, 0xc2, 0x75, 0x8f, 0x16, 0x98, + 0x49, 0xbc, 0x86, 0x54, 0x7f, 0x21, 0x8b, 0xb2, 0x33, 0x0f, 0x48, 0xe3, 0x98, 0x77, 0x8d, 0x70, + 0xb0, 0x99, 0x3d, 0xe4, 0xc1, 0xe6, 0x41, 0x7c, 0x2a, 0x5e, 0x0d, 0xfb, 0x33, 0x27, 0x57, 0x1f, + 0xe9, 0xf9, 0x68, 0xf5, 0x7e, 0x4f, 0x1f, 0x3f, 0x97, 0x9c, 0x7f, 0x9e, 0x41, 0x99, 0xda, 0x74, + 0xf5, 0x44, 0x6f, 0x8e, 0x54, 0x6f, 0x7a, 0xdf, 0x59, 0xab, 0xc1, 0x35, 0x54, 0x3e, 0xf4, 0x12, + 0x8d, 0xdc, 0x38, 0x7d, 0x23, 0x83, 0x46, 0x6b, 0xb3, 0xcb, 0x55, 0xe1, 0x24, 0xf8, 0x36, 0xf3, + 0xe4, 0x03, 0x9f, 0x32, 0xd6, 0xa5, 0x17, 0x62, 0xf6, 0xcc, 0x9d, 0x8a, 0xe5, 0x3d, 0x7f, 0xf3, + 0xae, 0xde, 0xec, 0x10, 0x38, 0x7a, 0x61, 0x7e, 0xbf, 0xae, 0xf9, 0x0e, 0xf9, 0x71, 0x78, 0xf8, + 0xef, 0x33, 0xc0, 0x1f, 0x43, 0x99, 0x3b, 0xdc, 0x23, 0xa3, 0x1b, 0x9f, 0x67, 0x6f, 0x30, 0x3e, + 0x74, 0x12, 0xcc, 0x74, 0x4c, 0x03, 0x38, 0xd0, 0x52, 0xb4, 0xf0, 0x2d, 0xbe, 0x00, 0xef, 0xa9, + 0xf0, 0x9a, 0x5f, 0xf8, 0x56, 0xa5, 0x8c, 0x6b, 0x68, 0xa8, 0x4a, 0x9c, 0x96, 0x09, 0x1d, 0xe5, + 0xcf, 0xd9, 0xbd, 0x99, 0xd0, 0x9d, 0xca, 0x50, 0x3b, 0x2c, 0x04, 0xcc, 0x44, 0x2e, 0xf8, 0x4d, + 0x84, 0x98, 0x8d, 0xb2, 0xc7, 0x20, 0x8c, 0x17, 0xc1, 0xee, 0x67, 0xa6, 0x65, 0x82, 0x8d, 0x27, + 0x30, 0xc3, 0x1b, 0xa8, 0xb0, 0x60, 0x1b, 0xe6, 0xaa, 0xc9, 0x5c, 0x2f, 0xa1, 0x82, 0xdc, 0xee, + 0x0e, 0x4f, 0xd4, 0x94, 0x6c, 0x09, 0xe5, 0x92, 0xaa, 0x89, 0x31, 0x56, 0xff, 0x49, 0x3f, 0xca, + 0xd2, 0x6e, 0x3f, 0x19, 0xbf, 0x87, 0x19, 0xbf, 0x25, 0x54, 0xb8, 0x67, 0x3b, 0x1b, 0xa6, 0xb5, + 0x16, 0x78, 0xc5, 0xf3, 0xbd, 0x29, 0x78, 0xf2, 0x6c, 0x32, 0x5c, 0x3d, 0x70, 0xa0, 0xd7, 0x62, + 0xe4, 0xbb, 0x8c, 0xe0, 0x17, 0x11, 0x62, 0x6f, 0xdd, 0x81, 0x26, 0x1f, 0x06, 0xab, 0x60, 0x2f, + 0xe1, 0xc1, 0xd1, 0x5e, 0x0c, 0x56, 0x11, 0x12, 0xd3, 0x4d, 0x38, 0xf3, 0x85, 0x18, 0x04, 0xbf, + 0x7b, 0xd8, 0x84, 0x83, 0x2f, 0x84, 0x68, 0x04, 0x30, 0xaf, 0x88, 0x2a, 0x42, 0xc2, 0xfd, 0x12, + 0x8a, 0x08, 0x42, 0x9a, 0x1c, 0x78, 0x78, 0xb8, 0x84, 0xeb, 0x25, 0x4d, 0xe0, 0x81, 0x9f, 0x8f, + 0x5c, 0x80, 0x63, 0x89, 0x5b, 0xd7, 0xfb, 0xef, 0xd0, 0x81, 0x6a, 0x78, 0x37, 0x07, 0x2a, 0xf5, + 0xf3, 0x69, 0x34, 0x58, 0xeb, 0xac, 0xb8, 0x5b, 0xae, 0x47, 0x5a, 0xc7, 0x5c, 0x8d, 0xfd, 0xed, + 0x55, 0x36, 0x71, 0x7b, 0xf5, 0xa4, 0x2f, 0x14, 0xe1, 0xdc, 0x31, 0x30, 0xe9, 0x7c, 0x71, 0xfc, + 0xc3, 0x34, 0x2a, 0xb0, 0x8b, 0xb3, 0xb2, 0xe9, 0x36, 0x1e, 0x82, 0x33, 0xff, 0xd1, 0x4b, 0xe5, + 0x70, 0x97, 0xcd, 0x7b, 0x78, 0x22, 0xa1, 0x7e, 0x36, 0x8d, 0x86, 0x4a, 0x1d, 0x6f, 0xbd, 0xe4, + 0x81, 0x6e, 0x3d, 0x92, 0xfb, 0x93, 0x5f, 0x4f, 0xa1, 0x31, 0xda, 0x90, 0x65, 0x7b, 0x83, 0x58, + 0x0f, 0xe1, 0xe0, 0x51, 0x3c, 0x40, 0x4c, 0x1f, 0xf0, 0x00, 0xd1, 0x97, 0x65, 0x66, 0x7f, 0xb2, + 0x84, 0xe3, 0x72, 0xcd, 0x6e, 0x92, 0xe3, 0xfd, 0x19, 0x0f, 0xf1, 0xb8, 0xdc, 0x17, 0xc8, 0x43, + 0xb8, 0x9e, 0x79, 0x7f, 0x09, 0xe4, 0x21, 0x9c, 0x2d, 0xbd, 0x3f, 0x04, 0xf2, 0xd5, 0x14, 0x1a, + 0x9c, 0xb2, 0xbd, 0x63, 0x3e, 0xf0, 0xf9, 0x57, 0x1c, 0x6f, 0x35, 0xf7, 0xbf, 0xe2, 0x78, 0xeb, + 0xa6, 0xfa, 0xc3, 0x69, 0x74, 0x9a, 0x07, 0xd8, 0xe6, 0xe7, 0x0f, 0x27, 0xd3, 0x31, 0x1f, 0x6c, + 0x71, 0xd1, 0x9c, 0xcc, 0x43, 0x5c, 0x34, 0x3f, 0x99, 0x41, 0xa7, 0x21, 0x94, 0x29, 0xdd, 0x96, + 0xbd, 0x0f, 0x6c, 0x11, 0xdc, 0x90, 0x2f, 0x41, 0x17, 0x12, 0x2e, 0x41, 0xff, 0x78, 0xbb, 0xf8, + 0xfc, 0x9a, 0xe9, 0xad, 0x77, 0x56, 0x26, 0x1b, 0x76, 0xeb, 0xfa, 0x9a, 0xa3, 0xdf, 0x37, 0xd9, + 0xf5, 0x9f, 0xde, 0xbc, 0x1e, 0xe4, 0xaa, 0xd0, 0xdb, 0x26, 0xcf, 0x62, 0x51, 0x83, 0xbd, 0x0e, + 0xe5, 0xea, 0x5f, 0x9f, 0xba, 0x08, 0xbd, 0x6e, 0x9b, 0x16, 0xf7, 0x29, 0x64, 0x86, 0x6e, 0x8d, + 0xee, 0x0f, 0xdf, 0xb6, 0x4d, 0xab, 0x1e, 0x75, 0x2c, 0xdc, 0x6f, 0x7d, 0x21, 0x6b, 0x4d, 0xa8, + 0x46, 0xfd, 0x37, 0x29, 0x74, 0x5e, 0xd6, 0xe2, 0xf7, 0x83, 0xed, 0xf8, 0x23, 0x69, 0x74, 0xe6, + 0x16, 0x08, 0x27, 0x70, 0xe4, 0x38, 0x99, 0xb7, 0xf8, 0xe0, 0x4c, 0x90, 0xcd, 0x89, 0x45, 0xd9, + 0x5d, 0x36, 0x27, 0x93, 0x3a, 0x97, 0xcd, 0x6f, 0xa4, 0xd0, 0xa9, 0xa5, 0x4a, 0x79, 0xfa, 0x7d, + 0x32, 0xa2, 0xe2, 0xdf, 0x73, 0xcc, 0x0d, 0xce, 0xd8, 0xf7, 0x1c, 0x73, 0xd3, 0x93, 0x7e, 0x4f, + 0xad, 0xb4, 0x30, 0xff, 0x7e, 0xd2, 0x37, 0xe9, 0x7b, 0xde, 0x07, 0xfa, 0x26, 0x7d, 0xcf, 0x31, + 0xd7, 0xb7, 0x7f, 0x96, 0x43, 0x43, 0xb7, 0x3b, 0x2b, 0x84, 0xbb, 0x84, 0x3c, 0xd2, 0xe7, 0xad, + 0x37, 0xd0, 0x10, 0x17, 0x03, 0xdc, 0x55, 0x08, 0x21, 0xeb, 0x78, 0x08, 0x12, 0x16, 0x15, 0x48, + 0x24, 0xc2, 0x17, 0x50, 0xf6, 0x2e, 0x71, 0x56, 0xc4, 0xd7, 0x9c, 0xf7, 0x89, 0xb3, 0xa2, 0x01, + 0x14, 0xcf, 0x87, 0x8e, 0xea, 0xa5, 0x6a, 0x05, 0xd2, 0x97, 0xf0, 0x6b, 0x12, 0xc8, 0xc7, 0x12, + 0x78, 0x9b, 0xe9, 0x6d, 0x93, 0x25, 0x3e, 0x11, 0x5f, 0x92, 0x47, 0x4b, 0xe2, 0x45, 0x34, 0x2e, + 0xba, 0x1b, 0xb1, 0xdc, 0x1d, 0xf9, 0x04, 0x76, 0x49, 0x59, 0x3b, 0xe2, 0x45, 0xf1, 0xab, 0x68, + 0xd8, 0x07, 0x82, 0xe3, 0xd4, 0x60, 0x18, 0x30, 0x3e, 0x60, 0x15, 0x49, 0xea, 0x23, 0x15, 0x10, + 0x19, 0xc0, 0xe1, 0x3f, 0x4a, 0x60, 0x10, 0x71, 0x44, 0x93, 0x0a, 0xe0, 0xe7, 0x80, 0x01, 0x3c, + 0xae, 0x00, 0x17, 0x91, 0x21, 0x78, 0xea, 0x08, 0x8e, 0xf0, 0x0e, 0x87, 0xb3, 0x07, 0xad, 0x12, + 0x19, 0x5e, 0x42, 0x28, 0xbc, 0xca, 0xe7, 0x61, 0x03, 0xf6, 0xed, 0x64, 0x20, 0xb0, 0x10, 0x2f, + 0xe1, 0x46, 0x0e, 0x72, 0x09, 0xa7, 0xfe, 0x56, 0x1a, 0x0d, 0x95, 0xda, 0xed, 0x60, 0x28, 0x3c, + 0x8d, 0x72, 0xa5, 0x76, 0xfb, 0x8e, 0x56, 0x11, 0x03, 0x88, 0xeb, 0xed, 0x76, 0xbd, 0xe3, 0x98, + 0xa2, 0x27, 0x26, 0x23, 0xc2, 0xd3, 0x68, 0xa4, 0xd4, 0x6e, 0x57, 0x3b, 0x2b, 0x4d, 0xb3, 0x21, + 0xe4, 0x23, 0x62, 0x69, 0xcf, 0xda, 0xed, 0x7a, 0x1b, 0x30, 0xd1, 0x84, 0x52, 0x72, 0x19, 0xfc, + 0x16, 0x04, 0xdb, 0xe1, 0xe9, 0x70, 0x58, 0xc2, 0x0d, 0x35, 0x08, 0x1d, 0x1e, 0xb6, 0x6d, 0x32, + 0x20, 0x62, 0x21, 0xd6, 0x2f, 0xf8, 0x81, 0xea, 0x69, 0x45, 0xb1, 0xb4, 0x37, 0x21, 0x4b, 0xfc, + 0x11, 0x34, 0x50, 0x6a, 0xb7, 0x85, 0x5b, 0x1e, 0x70, 0xe5, 0xa1, 0xa5, 0x22, 0x7d, 0xec, 0x93, + 0x4d, 0xbc, 0x8c, 0x46, 0xe5, 0xca, 0xf6, 0x15, 0xa2, 0xfd, 0x8f, 0x52, 0xf0, 0x41, 0xc7, 0xdc, + 0x93, 0xf8, 0x59, 0x94, 0x29, 0xb5, 0xdb, 0x7c, 0x3e, 0x3a, 0x95, 0xd0, 0x1f, 0xd1, 0x87, 0xc7, + 0xa5, 0x76, 0xdb, 0xff, 0xf4, 0x63, 0xfe, 0x24, 0xe1, 0x40, 0x9f, 0xfe, 0x55, 0xf6, 0xe9, 0xc7, + 0xfb, 0xb9, 0x80, 0xfa, 0x0b, 0x19, 0x34, 0x56, 0x6a, 0xb7, 0x4f, 0x42, 0xbb, 0x3f, 0xac, 0xe7, + 0xcd, 0xcf, 0x20, 0x24, 0x4c, 0x8f, 0x03, 0xc1, 0x83, 0xa9, 0x21, 0x61, 0x6a, 0x54, 0x52, 0x9a, + 0x40, 0xe4, 0xab, 0x5f, 0x7e, 0x5f, 0xea, 0xf7, 0xd9, 0x0c, 0x4c, 0xc5, 0xc7, 0x3d, 0x54, 0xd3, + 0x7b, 0xa5, 0xdb, 0x78, 0x1f, 0xe4, 0xf6, 0xd5, 0x07, 0xbf, 0x26, 0x0d, 0x1e, 0x08, 0x15, 0x7e, + 0xd2, 0x0b, 0xfd, 0x87, 0x32, 0x8b, 0x47, 0x45, 0x61, 0xf2, 0xf8, 0x31, 0x7e, 0xfa, 0x22, 0x1e, + 0xcd, 0xa8, 0x41, 0x51, 0x75, 0xd3, 0xd0, 0x22, 0xb4, 0x7e, 0x1f, 0x0e, 0xec, 0xab, 0x0f, 0xb7, + 0xd3, 0xf0, 0x62, 0x39, 0x88, 0x86, 0x74, 0xf8, 0xdd, 0xc5, 0x75, 0x84, 0xd8, 0x7d, 0x7f, 0xe0, + 0x4c, 0x3c, 0xc2, 0x02, 0x9f, 0xb0, 0xac, 0x46, 0x3c, 0xf0, 0x49, 0x48, 0x12, 0xf8, 0x25, 0x65, + 0x12, 0xfd, 0x92, 0xae, 0xa2, 0xbc, 0xa6, 0x6f, 0xbe, 0xd1, 0x21, 0xce, 0x16, 0x37, 0x67, 0x58, + 0xb0, 0x41, 0x7d, 0xb3, 0xfe, 0x19, 0x0a, 0xd4, 0x02, 0x34, 0x56, 0x83, 0x27, 0xef, 0x82, 0x1f, + 0x06, 0x3b, 0x99, 0x0e, 0x1e, 0xba, 0x1f, 0x44, 0xd1, 0xf1, 0x4b, 0x28, 0x53, 0xba, 0x57, 0xe3, + 0x92, 0x0d, 0xba, 0xb6, 0x74, 0xaf, 0xc6, 0xe5, 0xd5, 0xb5, 0xec, 0xbd, 0x9a, 0xfa, 0xd9, 0x34, + 0xc2, 0x71, 0x4a, 0xfc, 0x3c, 0x1a, 0x04, 0xe8, 0x1a, 0xd5, 0x19, 0x31, 0x1d, 0xe6, 0xa6, 0x5b, + 0x77, 0x00, 0x2a, 0x19, 0x77, 0x3e, 0x29, 0x7e, 0x11, 0xb2, 0xf6, 0xf2, 0x84, 0x6c, 0x52, 0x3a, + 0xcc, 0x4d, 0xd7, 0xcf, 0x73, 0x1b, 0x49, 0xda, 0xcb, 0x89, 0xc1, 0x2e, 0xbc, 0x57, 0x9b, 0xb3, + 0x5d, 0x8f, 0x8b, 0x9a, 0xd9, 0x85, 0x9b, 0x2e, 0xe4, 0x50, 0x95, 0xec, 0x42, 0x46, 0x06, 0xb9, + 0xa4, 0xee, 0xd5, 0xd8, 0xe3, 0x10, 0x43, 0xb3, 0x9b, 0xbe, 0x41, 0xc9, 0x72, 0x49, 0x6d, 0xba, + 0x75, 0xf6, 0xb0, 0xc4, 0x80, 0x74, 0xc1, 0x52, 0x2e, 0x29, 0xa9, 0x94, 0xfa, 0x7d, 0x79, 0x54, + 0x28, 0xeb, 0x9e, 0xbe, 0xa2, 0xbb, 0x44, 0xd8, 0x4d, 0x8f, 0xf9, 0x30, 0xff, 0x73, 0x04, 0x39, + 0x18, 0x2b, 0x09, 0x5f, 0x13, 0x2d, 0x80, 0x3f, 0x16, 0xf2, 0x0d, 0x32, 0x7d, 0x8a, 0xa9, 0xc3, + 0x56, 0xea, 0x6d, 0x0e, 0xd6, 0x62, 0x84, 0xf8, 0x1a, 0x1a, 0xf2, 0x61, 0x74, 0x03, 0x90, 0x09, + 0x75, 0xc6, 0x58, 0xa1, 0xf6, 0xbf, 0x26, 0xa2, 0xf1, 0x8b, 0x68, 0xd8, 0xff, 0x29, 0x98, 0xd6, + 0x2c, 0x0f, 0xda, 0x4a, 0x6c, 0xf7, 0x24, 0x92, 0x8a, 0x45, 0x61, 0x7e, 0xeb, 0x97, 0x8a, 0x46, + 0x52, 0x8d, 0x49, 0xa4, 0xf8, 0x33, 0x68, 0xd4, 0xff, 0xcd, 0x37, 0x0c, 0x2c, 0x2b, 0xdb, 0xb5, + 0x20, 0x1b, 0x71, 0x44, 0xac, 0x93, 0x32, 0x39, 0xdb, 0x3a, 0x3c, 0xe6, 0x67, 0xcf, 0x32, 0x56, + 0xe2, 0x3b, 0x87, 0x48, 0x05, 0xb8, 0x82, 0xc6, 0x7d, 0x48, 0xa8, 0xa1, 0x03, 0xe1, 0x8e, 0xd1, + 0x58, 0xa9, 0x27, 0x2a, 0x69, 0xbc, 0x14, 0x6e, 0xa2, 0x0b, 0x12, 0xd0, 0x70, 0xd7, 0xcd, 0x55, + 0x8f, 0x6f, 0xf7, 0x78, 0xe4, 0x5f, 0x9e, 0x2e, 0x31, 0xe0, 0xca, 0x68, 0xfc, 0xbc, 0xa7, 0x72, + 0x4e, 0xa6, 0x9e, 0xdc, 0x70, 0x0d, 0x9d, 0xf6, 0xf1, 0xb7, 0xa6, 0xab, 0x55, 0xc7, 0x7e, 0x9b, + 0x34, 0xbc, 0x4a, 0x99, 0x6f, 0x97, 0x21, 0x22, 0x9c, 0xb1, 0x52, 0x5f, 0x6b, 0xb4, 0xa9, 0x52, + 0x50, 0x9c, 0xcc, 0x3c, 0xb1, 0x30, 0xbe, 0x8b, 0xce, 0x08, 0xf0, 0x8a, 0xe5, 0x7a, 0xba, 0xd5, + 0x20, 0x95, 0x32, 0xdf, 0x43, 0xc3, 0x7e, 0x9e, 0x73, 0x35, 0x39, 0x52, 0x66, 0x9b, 0x5c, 0x1c, + 0xbf, 0x8c, 0x46, 0x7c, 0x04, 0xbb, 0xbb, 0x1b, 0x82, 0xbb, 0x3b, 0x18, 0x92, 0xc6, 0x4a, 0x3d, + 0xfa, 0x86, 0x51, 0x26, 0x16, 0x35, 0x0a, 0x92, 0xc1, 0x0f, 0x4b, 0x1a, 0xe5, 0x6d, 0xb5, 0x13, + 0x95, 0x11, 0x12, 0xc4, 0xbf, 0x1a, 0x6a, 0xd4, 0x92, 0x63, 0xae, 0x99, 0x6c, 0x27, 0xed, 0x3f, + 0x5b, 0x5c, 0xa9, 0xdb, 0x00, 0x4c, 0xd2, 0x0f, 0x46, 0x3e, 0x51, 0x42, 0xa7, 0x12, 0x74, 0x6c, + 0x5f, 0x3b, 0xc6, 0xcf, 0xa7, 0xc3, 0x46, 0x1c, 0xf3, 0x6d, 0xe3, 0x14, 0xca, 0xfb, 0x5f, 0xc2, + 0x8d, 0x07, 0xa5, 0xdb, 0xd0, 0x8c, 0xf2, 0xf0, 0xf1, 0x92, 0x38, 0x8e, 0xf9, 0x56, 0xf2, 0x61, + 0x88, 0xe3, 0xdd, 0x54, 0x28, 0x8e, 0x63, 0xbe, 0xbd, 0xfc, 0x8d, 0x4c, 0x38, 0x27, 0x9d, 0xec, + 0x31, 0x1f, 0x96, 0x99, 0x1c, 0x7a, 0x9f, 0xe6, 0xf6, 0xf1, 0x7c, 0x50, 0x54, 0xcd, 0x81, 0x03, + 0xaa, 0xe6, 0xef, 0xc4, 0xfb, 0x93, 0x99, 0x9e, 0xc7, 0xb2, 0x3f, 0x1f, 0xc2, 0x60, 0xc5, 0x37, + 0xc2, 0x75, 0x8c, 0xd9, 0xe8, 0xfd, 0x42, 0x60, 0xbd, 0x15, 0x6e, 0xa2, 0xcb, 0x24, 0xf8, 0x53, + 0xe8, 0x9c, 0x04, 0xa8, 0xea, 0x8e, 0xde, 0x22, 0x5e, 0x98, 0xe7, 0x0f, 0x42, 0x25, 0xf9, 0xa5, + 0xeb, 0xed, 0x00, 0x2d, 0xe6, 0x0e, 0xec, 0xc2, 0x41, 0x50, 0x8e, 0x81, 0x7d, 0xb8, 0x26, 0xff, + 0xfb, 0x2c, 0x52, 0x02, 0x03, 0x31, 0x78, 0x84, 0x73, 0x84, 0x93, 0xf1, 0x7b, 0xa2, 0x73, 0x4d, + 0x34, 0x1e, 0x0a, 0xa3, 0xd6, 0x69, 0xb5, 0x74, 0xe8, 0x60, 0x6a, 0x80, 0x16, 0xa3, 0xcc, 0x42, + 0x42, 0x66, 0x73, 0x4e, 0x70, 0x9b, 0x13, 0x87, 0x8f, 0x9c, 0xea, 0x2e, 0x63, 0xa1, 0xc5, 0xb9, + 0xe2, 0x2f, 0xa4, 0xd0, 0xe9, 0xd2, 0xea, 0x2a, 0x69, 0x78, 0xc4, 0x58, 0x5a, 0xa1, 0xc6, 0xd7, + 0xb4, 0xdd, 0xb1, 0x3c, 0xdf, 0xde, 0x7d, 0xa9, 0x7b, 0x75, 0xac, 0x93, 0x26, 0x93, 0x0a, 0xb3, + 0x96, 0x04, 0x41, 0x03, 0x74, 0x4e, 0x52, 0xb7, 0x81, 0xa6, 0xde, 0x00, 0x22, 0x2d, 0xb1, 0xde, + 0x89, 0x5b, 0xe8, 0x7c, 0x57, 0x96, 0xbb, 0x19, 0x3b, 0xfd, 0xa2, 0xb1, 0xf3, 0xef, 0x52, 0xa1, + 0xba, 0x47, 0x84, 0x84, 0x27, 0x11, 0x0a, 0x41, 0x7c, 0xfb, 0x33, 0xba, 0xb3, 0x5d, 0x44, 0xa1, + 0xd0, 0x34, 0x81, 0x02, 0x2f, 0xa1, 0x1c, 0x17, 0x0b, 0xcb, 0xdc, 0xfa, 0xe1, 0x5d, 0x7a, 0x61, + 0x52, 0x94, 0x03, 0x6c, 0x6d, 0xf8, 0x37, 0x73, 0x36, 0x13, 0x2f, 0xa2, 0xa1, 0x83, 0x7e, 0xd7, + 0x17, 0x32, 0x08, 0x8b, 0x7b, 0x95, 0x23, 0x34, 0xe4, 0xde, 0x13, 0x83, 0xe5, 0x60, 0x99, 0x57, + 0xae, 0xa0, 0x3c, 0xfd, 0x04, 0xc8, 0x65, 0x20, 0xc4, 0x2e, 0xed, 0x70, 0x98, 0x16, 0x60, 0xc3, + 0xc0, 0x41, 0x03, 0xc9, 0x81, 0x83, 0xd4, 0x1f, 0xc8, 0xa0, 0xb3, 0x62, 0x87, 0x94, 0x09, 0x84, + 0x43, 0x3f, 0xe9, 0x94, 0x6f, 0x62, 0xa7, 0xa8, 0x28, 0xc7, 0x4c, 0x54, 0x1e, 0x97, 0x9e, 0x1d, + 0x1f, 0x00, 0x44, 0xe3, 0x18, 0xf5, 0xbf, 0xa4, 0xd1, 0x48, 0xd5, 0x76, 0xbd, 0x35, 0x87, 0xb8, + 0x55, 0xdd, 0x71, 0x1f, 0xe1, 0xee, 0xf8, 0x28, 0x1a, 0x81, 0xd0, 0x2f, 0x2d, 0x62, 0xb1, 0xf0, + 0x28, 0xfd, 0x42, 0x22, 0x09, 0x1f, 0xc1, 0x73, 0x06, 0x49, 0x84, 0x54, 0xfb, 0x99, 0x7d, 0x21, + 0x04, 0xe4, 0x61, 0xc6, 0x05, 0x83, 0xab, 0x7f, 0x3b, 0x83, 0x86, 0x7d, 0x29, 0x4f, 0x99, 0xc7, + 0xf5, 0x3e, 0xe0, 0x68, 0x85, 0x7c, 0x1d, 0xa1, 0xaa, 0xed, 0x78, 0x7a, 0x73, 0x31, 0xd4, 0x7c, + 0x38, 0x48, 0x6b, 0x03, 0x94, 0x95, 0x11, 0x48, 0x60, 0xfd, 0x0a, 0x8d, 0x37, 0x36, 0x31, 0xb1, + 0xf5, 0x2b, 0x80, 0x6a, 0x02, 0x85, 0xfa, 0x2b, 0x69, 0x34, 0xe6, 0x77, 0xd2, 0xcc, 0x03, 0xd2, + 0xe8, 0x3c, 0xca, 0x73, 0x93, 0x2c, 0xed, 0xfe, 0x5d, 0xa5, 0xad, 0xfe, 0x4f, 0x61, 0x22, 0x99, + 0x6e, 0xda, 0x27, 0x13, 0xc9, 0x9f, 0x85, 0x8e, 0xab, 0xdf, 0x91, 0x41, 0xa7, 0x7d, 0xa9, 0xcf, + 0x76, 0x2c, 0xd8, 0x82, 0x4e, 0xeb, 0xcd, 0xe6, 0xa3, 0xbc, 0xe7, 0x1b, 0xf2, 0x05, 0xb1, 0xc4, + 0x63, 0xa9, 0xf1, 0xfc, 0x6d, 0xab, 0x1c, 0x5c, 0xb7, 0x4d, 0x43, 0x13, 0x89, 0xf0, 0xab, 0x68, + 0xd8, 0xff, 0x59, 0x72, 0xd6, 0xfc, 0x8d, 0x1e, 0x1c, 0x28, 0x07, 0x85, 0x74, 0x47, 0x7a, 0x32, + 0x2e, 0x15, 0x50, 0xff, 0x5b, 0x0e, 0x4d, 0xdc, 0x33, 0x2d, 0xc3, 0xde, 0x74, 0xfd, 0xf4, 0x7f, + 0xc7, 0xfe, 0x40, 0xe5, 0xa8, 0xd3, 0xfe, 0xbd, 0x81, 0xce, 0x44, 0x45, 0xea, 0x04, 0x41, 0x99, + 0x79, 0xef, 0x6c, 0x32, 0x82, 0xba, 0x9f, 0x08, 0x90, 0xdf, 0xca, 0x68, 0xc9, 0x25, 0xa3, 0x99, + 0x04, 0x07, 0xf6, 0x92, 0x49, 0xf0, 0x29, 0x94, 0x2b, 0xdb, 0x2d, 0xdd, 0xf4, 0x83, 0x87, 0xc0, + 0x28, 0x0e, 0xea, 0x05, 0x8c, 0xc6, 0x29, 0x28, 0x7f, 0x5e, 0x31, 0x74, 0xd9, 0x60, 0xc8, 0xdf, + 0x2f, 0x40, 0xad, 0x34, 0x4d, 0x24, 0xc2, 0x36, 0x1a, 0xe1, 0xd5, 0xf1, 0x3b, 0x14, 0x04, 0x9b, + 0xa7, 0xe7, 0x7c, 0x19, 0x75, 0x57, 0xab, 0x49, 0xa9, 0x1c, 0xdb, 0x46, 0xb1, 0x04, 0x87, 0xfc, + 0x63, 0xd8, 0x6d, 0x8a, 0x26, 0xf3, 0x17, 0x84, 0x00, 0x93, 0xcc, 0x50, 0x5c, 0x08, 0x30, 0xcb, + 0x88, 0x44, 0x78, 0x06, 0x8d, 0x43, 0xe8, 0xdc, 0x60, 0x2b, 0x45, 0x55, 0x62, 0x18, 0x8c, 0x4a, + 0x38, 0x9a, 0x67, 0xd1, 0x76, 0xe9, 0xc7, 0xd5, 0x1b, 0x1c, 0xad, 0xc5, 0x4b, 0x4c, 0xbc, 0x86, + 0x70, 0xbc, 0xcd, 0xfb, 0x3a, 0x9c, 0xff, 0xbe, 0x74, 0xb8, 0xaf, 0x3b, 0xee, 0xee, 0x15, 0x0f, + 0xe3, 0x38, 0xfa, 0x67, 0x52, 0x68, 0x3c, 0x16, 0x8a, 0x19, 0x3f, 0x8b, 0x10, 0x83, 0x08, 0x21, + 0xef, 0x20, 0x86, 0x44, 0x18, 0x9e, 0x99, 0x2f, 0x25, 0x21, 0x19, 0xbe, 0x8e, 0xf2, 0xec, 0x17, + 0x0f, 0x53, 0x13, 0x2f, 0xd2, 0xe9, 0x98, 0x86, 0x16, 0x10, 0x85, 0xb5, 0xc0, 0x2d, 0x4f, 0x26, + 0xb1, 0x88, 0xb7, 0xd5, 0x0e, 0x6a, 0xa1, 0x64, 0xb4, 0x03, 0x87, 0x83, 0x06, 0x97, 0x8c, 0xa3, + 0xea, 0xba, 0x1c, 0x8f, 0x6a, 0x9d, 0xd9, 0x2d, 0xaa, 0x75, 0x64, 0x6e, 0xe2, 0x61, 0xac, 0x1f, + 0xde, 0xd3, 0x90, 0x2f, 0xa6, 0xd1, 0x58, 0x50, 0xeb, 0x11, 0x5e, 0x28, 0xbc, 0x87, 0x44, 0xf2, + 0x85, 0x14, 0x52, 0xa6, 0xcc, 0x66, 0xd3, 0xb4, 0xd6, 0x2a, 0xd6, 0xaa, 0xed, 0xb4, 0x60, 0xf2, + 0x38, 0xba, 0xe3, 0x4e, 0xf5, 0xbb, 0x53, 0x68, 0x9c, 0x37, 0x68, 0x5a, 0x77, 0x8c, 0xa3, 0x3b, + 0x4b, 0x8a, 0xb6, 0xe4, 0xe8, 0xf4, 0x45, 0xfd, 0x72, 0x1a, 0xa1, 0x79, 0xbb, 0xb1, 0x71, 0xcc, + 0xdf, 0x06, 0x7e, 0x0c, 0xe5, 0x58, 0xac, 0x20, 0xae, 0xb1, 0xe3, 0x93, 0xec, 0xc9, 0x27, 0xfd, + 0x34, 0x86, 0x98, 0x2a, 0xf0, 0x13, 0xda, 0x1c, 0x8b, 0x35, 0xa4, 0xa4, 0x34, 0x5e, 0x84, 0x56, + 0x4a, 0xe9, 0xb8, 0x55, 0x13, 0x54, 0x4a, 0x61, 0x72, 0xa5, 0x3b, 0xdb, 0xc5, 0x6c, 0xd3, 0x6e, + 0x6c, 0x68, 0x40, 0xaf, 0xfe, 0x49, 0x8a, 0xc9, 0xee, 0x98, 0xbf, 0x8f, 0xf3, 0x3f, 0x3f, 0xbb, + 0xcf, 0xcf, 0xff, 0xde, 0x14, 0x3a, 0xad, 0x91, 0x86, 0x7d, 0x9f, 0x38, 0x5b, 0xd3, 0xb6, 0x41, + 0x6e, 0x11, 0x8b, 0x38, 0x47, 0x35, 0xa2, 0xfe, 0x31, 0xa4, 0x01, 0x08, 0x1b, 0x73, 0xc7, 0x25, + 0xc6, 0xf1, 0x49, 0xd1, 0xa0, 0xfe, 0xa3, 0x01, 0xa4, 0x24, 0x5a, 0x88, 0xc7, 0xd6, 0x2a, 0xea, + 0x6a, 0xf6, 0x67, 0x1f, 0x96, 0xd9, 0xdf, 0xbf, 0x3f, 0xb3, 0x3f, 0xb7, 0x5f, 0xb3, 0x7f, 0x60, + 0x2f, 0x66, 0x7f, 0x2b, 0x6a, 0xf6, 0xe7, 0xc1, 0xec, 0x7f, 0xb6, 0xa7, 0xd9, 0x3f, 0x63, 0x19, + 0x07, 0x34, 0xfa, 0x8f, 0x6d, 0xfa, 0xd0, 0x83, 0xec, 0x56, 0xae, 0xd0, 0x49, 0xb1, 0x61, 0x3b, + 0x06, 0x31, 0xf8, 0x26, 0x05, 0x4e, 0xc8, 0x1d, 0x0e, 0xd3, 0x02, 0x6c, 0x2c, 0x17, 0xeb, 0xc8, + 0x5e, 0x72, 0xb1, 0x3e, 0x84, 0x6d, 0xcc, 0xe7, 0xd3, 0x68, 0x7c, 0x9a, 0x38, 0x1e, 0x0b, 0x46, + 0xf8, 0x30, 0xdc, 0x8c, 0x4a, 0x68, 0x4c, 0x60, 0x08, 0x16, 0x79, 0x3a, 0x74, 0x9d, 0x6a, 0x10, + 0xc7, 0x8b, 0x7a, 0x5e, 0x45, 0xe9, 0x69, 0xf5, 0x7e, 0x3e, 0x24, 0x3e, 0x76, 0x83, 0xea, 0x7d, + 0x38, 0x13, 0xa4, 0xc9, 0x7f, 0x69, 0x01, 0xbd, 0x90, 0xe2, 0x28, 0xbb, 0xff, 0x14, 0x47, 0xea, + 0x4f, 0xa7, 0xd0, 0x65, 0x8d, 0x58, 0x64, 0x53, 0x5f, 0x69, 0x12, 0xa1, 0x59, 0x7c, 0x65, 0xa0, + 0xb3, 0x86, 0xe9, 0xb6, 0x74, 0xaf, 0xb1, 0x7e, 0x28, 0x19, 0xcd, 0xa2, 0x61, 0x71, 0xfe, 0xda, + 0xc7, 0xdc, 0x26, 0x95, 0x53, 0x7f, 0x39, 0x83, 0x06, 0xa6, 0x6c, 0xef, 0x75, 0xfb, 0x90, 0x39, + 0xb7, 0xc2, 0x29, 0x3f, 0xbd, 0x8f, 0x73, 0x91, 0x8f, 0x40, 0xe5, 0x42, 0x18, 0x72, 0x70, 0xcb, + 0x5b, 0xb1, 0x63, 0xe1, 0xda, 0x7d, 0xb2, 0x7d, 0x66, 0xdb, 0x7a, 0x1e, 0x0d, 0x42, 0x1c, 0x0b, + 0xe1, 0xe4, 0x12, 0x9c, 0x5e, 0x3d, 0x0a, 0x8c, 0xd6, 0x11, 0x92, 0xe2, 0x4f, 0x49, 0xd1, 0x13, + 0x73, 0x87, 0xcf, 0xce, 0x25, 0x06, 0x52, 0x7c, 0x68, 0x49, 0xb0, 0xd4, 0x6f, 0x64, 0xd1, 0xb0, + 0xef, 0xea, 0x78, 0x44, 0x3d, 0xf8, 0x34, 0xca, 0xcd, 0xd9, 0x42, 0x48, 0x75, 0x70, 0x8d, 0x5c, + 0xb7, 0xdd, 0x88, 0xcf, 0x27, 0x27, 0xc2, 0xcf, 0xa2, 0xfc, 0xa2, 0x6d, 0x88, 0x8e, 0xbd, 0x30, + 0xa6, 0x2d, 0xdb, 0x88, 0x3d, 0x8c, 0x0c, 0x08, 0xf1, 0x65, 0x94, 0x05, 0x9f, 0x68, 0xe1, 0xe8, + 0x39, 0xe2, 0x07, 0x0d, 0x78, 0x41, 0x37, 0x72, 0xfb, 0xd5, 0x8d, 0x81, 0x83, 0xea, 0x46, 0xfe, + 0xe1, 0xea, 0xc6, 0x9b, 0x68, 0x18, 0x6a, 0xf2, 0x33, 0x32, 0xed, 0xbe, 0xbc, 0x9d, 0xe7, 0x2b, + 0xd0, 0x08, 0x6b, 0x37, 0xcf, 0xcb, 0x04, 0x0b, 0x8f, 0xc4, 0x2a, 0xa2, 0x76, 0xe8, 0x10, 0x6a, + 0xf7, 0x3b, 0x29, 0x34, 0x70, 0xc7, 0xda, 0xb0, 0xec, 0xcd, 0xc3, 0x69, 0xdc, 0xb3, 0x68, 0x88, + 0xb3, 0x11, 0xe6, 0x78, 0x78, 0xeb, 0xda, 0x61, 0xe0, 0x3a, 0x70, 0xd2, 0x44, 0x2a, 0xfc, 0x72, + 0x50, 0x08, 0x9e, 0x3d, 0x64, 0xc2, 0xa4, 0x04, 0x7e, 0xa1, 0x86, 0x1c, 0x47, 0x5d, 0x24, 0xc7, + 0x17, 0x50, 0xb6, 0x4c, 0x9b, 0x2a, 0x44, 0xe5, 0xa4, 0x4d, 0xd1, 0x00, 0xaa, 0xfe, 0xab, 0x34, + 0x1a, 0x8d, 0x1c, 0x3f, 0x3d, 0x85, 0x06, 0xf9, 0xf1, 0x8f, 0xe9, 0x07, 0x76, 0x87, 0x67, 0x11, + 0x01, 0x50, 0xcb, 0xb3, 0x3f, 0x2b, 0x06, 0xfe, 0x38, 0x1a, 0xb0, 0x5d, 0x58, 0x9a, 0xe0, 0x5b, + 0x46, 0xc3, 0x21, 0xb4, 0x54, 0xa3, 0x6d, 0x67, 0x83, 0x83, 0x93, 0x88, 0x1a, 0x69, 0xbb, 0xf0, + 0x69, 0x37, 0xd1, 0xa0, 0xee, 0xba, 0xc4, 0xab, 0x7b, 0xfa, 0x9a, 0x18, 0xeb, 0x3d, 0x00, 0x8a, + 0xa3, 0x03, 0x80, 0xcb, 0xfa, 0x1a, 0x7e, 0x0d, 0x8d, 0x34, 0x1c, 0x02, 0x8b, 0x97, 0xde, 0xa4, + 0xad, 0x14, 0x8c, 0x4b, 0x09, 0x21, 0x9e, 0xf8, 0x87, 0x88, 0x8a, 0x81, 0xef, 0xa2, 0x11, 0xfe, + 0x39, 0xcc, 0x27, 0x19, 0x06, 0xda, 0x68, 0xb8, 0x98, 0x30, 0x91, 0x30, 0xaf, 0x64, 0xee, 0x9a, + 0x2e, 0x92, 0x8b, 0x7c, 0x0d, 0x81, 0x54, 0xfd, 0x5a, 0x8a, 0x1a, 0x3c, 0x14, 0x00, 0x39, 0x52, + 0xa9, 0xae, 0xb4, 0xf6, 0xa9, 0x2b, 0xad, 0x30, 0x9b, 0x59, 0xce, 0xed, 0x31, 0x3b, 0x69, 0x1c, + 0x8b, 0x27, 0x51, 0xce, 0x10, 0xcf, 0x7e, 0xce, 0xca, 0x1f, 0xe1, 0xd7, 0xa3, 0x71, 0x2a, 0x7c, + 0x05, 0x65, 0xa9, 0x41, 0x1b, 0xdd, 0xf8, 0x89, 0x6b, 0xa4, 0x06, 0x14, 0xea, 0xb7, 0xa5, 0xd1, + 0xb0, 0xf0, 0x35, 0x37, 0x0e, 0xf5, 0x39, 0x2f, 0xed, 0xad, 0x99, 0xbe, 0x9b, 0x03, 0xec, 0x08, + 0xfc, 0x26, 0xdf, 0x0c, 0x44, 0xb1, 0xa7, 0x2b, 0x08, 0x2e, 0x98, 0xe7, 0xf9, 0x87, 0xe6, 0xf6, + 0xbe, 0x09, 0xa2, 0xf4, 0xaf, 0x67, 0xf3, 0xe9, 0x42, 0xe6, 0xf5, 0x6c, 0x3e, 0x5b, 0xe8, 0x57, + 0xff, 0xf4, 0x93, 0xa8, 0x7f, 0xc9, 0x22, 0x4b, 0xab, 0xf8, 0x19, 0x21, 0x57, 0x27, 0xff, 0xf8, + 0x71, 0x91, 0x25, 0x20, 0xe6, 0xfa, 0x34, 0x21, 0xa3, 0xe7, 0x4d, 0x31, 0x69, 0x1b, 0xef, 0x45, + 0x2c, 0x96, 0x61, 0x98, 0xb9, 0x3e, 0x4d, 0x4c, 0xee, 0x76, 0x53, 0x4c, 0x96, 0xc5, 0x85, 0x25, + 0x95, 0x62, 0x18, 0xbf, 0x14, 0x3f, 0x86, 0x98, 0x4f, 0xca, 0x28, 0x15, 0x3d, 0xc8, 0x8b, 0x53, + 0xcc, 0xf5, 0x69, 0xc9, 0x99, 0xa8, 0x86, 0xc5, 0xbb, 0x8a, 0xe8, 0x19, 0x89, 0x88, 0x9b, 0xeb, + 0xd3, 0x24, 0x5a, 0xfc, 0x42, 0x90, 0xd1, 0x97, 0x2e, 0xd0, 0xd1, 0xe7, 0x50, 0x02, 0x6a, 0xae, + 0x4f, 0x13, 0x29, 0x85, 0x4a, 0xab, 0x8e, 0x19, 0xa4, 0xdb, 0x8c, 0x56, 0x0a, 0x38, 0xa1, 0x52, + 0xf8, 0x8d, 0x5f, 0x41, 0x23, 0xc1, 0x3b, 0xb3, 0xb7, 0x49, 0xc3, 0xe3, 0xab, 0xd4, 0x99, 0x48, + 0x61, 0x86, 0x9c, 0xeb, 0xd3, 0x64, 0x6a, 0x7c, 0x05, 0xe5, 0x34, 0xe2, 0x9a, 0xef, 0xf8, 0xbb, + 0xab, 0x51, 0xe1, 0x18, 0xc6, 0x7c, 0x87, 0x4a, 0x89, 0xe3, 0x69, 0xef, 0x84, 0xdb, 0x39, 0xbe, + 0xa6, 0xe0, 0x48, 0x2d, 0x33, 0x96, 0x41, 0x7b, 0x47, 0xd8, 0xcb, 0xbf, 0x16, 0xcd, 0x76, 0x0f, + 0x5b, 0x21, 0xc9, 0xcd, 0x59, 0xc4, 0xce, 0xf5, 0x69, 0xd1, 0xec, 0xf8, 0x2f, 0x48, 0x99, 0xd6, + 0x79, 0xc0, 0x83, 0xa8, 0x54, 0x29, 0x4a, 0x90, 0x2a, 0xe4, 0x64, 0x7f, 0x2d, 0x9a, 0xfa, 0x9b, + 0x87, 0x37, 0x38, 0x9b, 0x9c, 0x20, 0x5a, 0xa8, 0xda, 0x4f, 0x15, 0xfe, 0x82, 0x94, 0xa2, 0x59, + 0x19, 0x4d, 0xae, 0x5a, 0xf7, 0x74, 0xb1, 0x6a, 0x36, 0xe4, 0xa5, 0x64, 0xc1, 0x90, 0xb0, 0x28, + 0xde, 0xa1, 0x80, 0x13, 0x3a, 0x94, 0x25, 0x16, 0x7e, 0x41, 0x4a, 0x4a, 0xc3, 0x33, 0x12, 0x05, + 0x95, 0x0a, 0x28, 0x5a, 0xa9, 0x98, 0xbe, 0xe6, 0xa6, 0x98, 0xab, 0x45, 0x19, 0x97, 0x3b, 0x28, + 0xc4, 0xd0, 0x0e, 0x12, 0x72, 0xba, 0x14, 0x21, 0x0f, 0x84, 0x82, 0x81, 0x7c, 0x28, 0x68, 0xe1, + 0x74, 0x75, 0xae, 0x4f, 0x83, 0x0c, 0x11, 0x2a, 0xcb, 0x30, 0xa2, 0x9c, 0x02, 0x8a, 0xe1, 0x20, + 0x15, 0xf6, 0x03, 0xd2, 0x98, 0xeb, 0xd3, 0x58, 0xf6, 0x91, 0x67, 0x84, 0x58, 0xde, 0xca, 0x69, + 0x79, 0x8a, 0x08, 0x10, 0x74, 0x8a, 0x08, 0x23, 0x7e, 0xcf, 0xc6, 0xe3, 0x5d, 0x2b, 0x67, 0xe4, + 0x93, 0xc0, 0x28, 0x7e, 0xae, 0x4f, 0x8b, 0xc7, 0xc8, 0x7e, 0x41, 0x0a, 0x01, 0xad, 0x9c, 0x8d, + 0xbc, 0x41, 0x0c, 0x51, 0x54, 0x5c, 0x62, 0xb0, 0xe8, 0xa5, 0xc4, 0xa4, 0x6d, 0xca, 0x39, 0x60, + 0xf0, 0x58, 0xc0, 0x20, 0x4e, 0x32, 0xd7, 0xa7, 0x25, 0xa6, 0x7b, 0x9b, 0x8e, 0x05, 0x62, 0x56, + 0x14, 0xf9, 0x28, 0x29, 0x82, 0x9e, 0xeb, 0xd3, 0x62, 0xa1, 0x9b, 0x6f, 0x8a, 0x11, 0x90, 0x95, + 0xf3, 0x72, 0x27, 0x86, 0x18, 0xda, 0x89, 0x42, 0xa4, 0xe4, 0x9b, 0x62, 0x54, 0x5c, 0x65, 0x22, + 0x5e, 0x2a, 0x9c, 0x39, 0x85, 0xe8, 0xb9, 0x5a, 0x72, 0xa0, 0x4f, 0xe5, 0x31, 0x9e, 0x6a, 0x81, + 0x97, 0x4f, 0xa2, 0x99, 0xeb, 0xd3, 0x92, 0x83, 0x84, 0x6a, 0xc9, 0x11, 0x32, 0x95, 0x0b, 0xbd, + 0x78, 0x06, 0xad, 0x4b, 0x8e, 0xae, 0xa9, 0xf7, 0x88, 0x57, 0xa8, 0x5c, 0x94, 0x03, 0xa0, 0x74, + 0x25, 0x9c, 0xeb, 0xd3, 0x7a, 0x44, 0x3d, 0xbc, 0xd3, 0x25, 0x78, 0xa0, 0x72, 0x49, 0xce, 0xb4, + 0x92, 0x48, 0x34, 0xd7, 0xa7, 0x75, 0x09, 0x3d, 0x78, 0xa7, 0x4b, 0x6c, 0x39, 0xa5, 0xd8, 0x93, + 0x6d, 0x20, 0x8f, 0x2e, 0x91, 0xe9, 0x96, 0x12, 0xc3, 0xb2, 0x29, 0x8f, 0xcb, 0xaa, 0x9b, 0x40, + 0x42, 0x55, 0x37, 0x29, 0xa0, 0xdb, 0x52, 0x62, 0x1c, 0x31, 0xe5, 0x89, 0x1e, 0x0c, 0x83, 0x36, + 0x26, 0x46, 0x20, 0x5b, 0x4a, 0x0c, 0xe4, 0xa5, 0xa8, 0x32, 0xc3, 0x04, 0x12, 0xca, 0x30, 0x29, + 0x04, 0xd8, 0x52, 0x62, 0xe4, 0x29, 0xe5, 0xc9, 0x1e, 0x0c, 0xc3, 0x16, 0x26, 0xc5, 0xac, 0x7a, + 0x41, 0x0a, 0xfd, 0xa4, 0x7c, 0x40, 0x9e, 0x37, 0x04, 0x14, 0x9d, 0x37, 0xc4, 0x20, 0x51, 0xd3, + 0xb1, 0xe0, 0x16, 0xca, 0x07, 0xe5, 0x61, 0x1e, 0x41, 0xd3, 0x61, 0x1e, 0x0d, 0x87, 0x31, 0x1d, + 0x7b, 0xe4, 0xaf, 0x5c, 0xee, 0xc6, 0x04, 0xd0, 0x32, 0x13, 0x16, 0x16, 0xa0, 0x92, 0xf0, 0xca, + 0x5c, 0xf9, 0x90, 0x7c, 0x0d, 0x1a, 0x23, 0x98, 0xeb, 0xd3, 0x12, 0xde, 0xa6, 0x6b, 0xc9, 0x4f, + 0xaa, 0x94, 0x2b, 0xf2, 0xb0, 0x4d, 0xa2, 0xa1, 0xc3, 0x36, 0xf1, 0x39, 0xd6, 0x7c, 0x92, 0xcb, + 0x83, 0x72, 0x55, 0x36, 0xcc, 0xe2, 0x14, 0xd4, 0x30, 0x4b, 0x70, 0x95, 0xd0, 0x92, 0x1f, 0x09, + 0x29, 0x4f, 0xf5, 0x6c, 0x21, 0xd0, 0x24, 0xb4, 0x90, 0xbd, 0x99, 0x09, 0x6d, 0xa7, 0x3b, 0xed, + 0xa6, 0xad, 0x1b, 0xca, 0x87, 0x13, 0x6d, 0x27, 0x86, 0x14, 0x6c, 0x27, 0x06, 0xa0, 0xab, 0xbc, + 0xe8, 0x12, 0xa0, 0x5c, 0x93, 0x57, 0x79, 0x11, 0x47, 0x57, 0x79, 0xc9, 0x7d, 0x60, 0x3a, 0x76, + 0x7d, 0xae, 0x3c, 0x2d, 0x2b, 0x40, 0x04, 0x4d, 0x15, 0x20, 0x7a, 0xe1, 0xfe, 0x56, 0xf7, 0x0b, + 0x67, 0x65, 0x12, 0xb8, 0x3d, 0xee, 0x73, 0xeb, 0x46, 0x37, 0xd7, 0xa7, 0x75, 0xbf, 0xb4, 0xae, + 0x24, 0xdc, 0x1f, 0x2b, 0xd7, 0x65, 0x05, 0x8b, 0x11, 0x50, 0x05, 0x8b, 0xdf, 0x3a, 0x57, 0x12, + 0x2e, 0x80, 0x95, 0x8f, 0x74, 0x65, 0x15, 0x7c, 0x73, 0xc2, 0xb5, 0xf1, 0x4d, 0xf1, 0x06, 0x57, + 0x79, 0x46, 0x5e, 0xec, 0x42, 0x0c, 0x5d, 0xec, 0x84, 0x9b, 0xde, 0x9b, 0xe2, 0xdd, 0xa5, 0x72, + 0x23, 0x5e, 0x2a, 0x5c, 0x22, 0x85, 0x3b, 0x4e, 0x2d, 0xf9, 0xca, 0x4f, 0x79, 0x56, 0xd6, 0xba, + 0x24, 0x1a, 0xaa, 0x75, 0x89, 0xd7, 0x85, 0xb3, 0xf1, 0x9b, 0x3b, 0xe5, 0x66, 0xf4, 0x0e, 0x54, + 0xc6, 0x53, 0xcb, 0x27, 0x76, 0xdb, 0xf7, 0x5a, 0xf4, 0xbd, 0xaf, 0xf2, 0x5c, 0x64, 0x7f, 0x29, + 0x61, 0xa9, 0x7d, 0x1b, 0x79, 0x1f, 0xfc, 0x5a, 0xf4, 0x89, 0xac, 0xf2, 0x7c, 0x32, 0x87, 0x40, + 0x57, 0xa2, 0x4f, 0x6a, 0x5f, 0x8b, 0xbe, 0x2a, 0x55, 0x5e, 0x48, 0xe6, 0x10, 0x48, 0x37, 0xfa, + 0x0a, 0xf5, 0x19, 0x21, 0xce, 0x95, 0xf2, 0x51, 0xd9, 0x74, 0x0c, 0x10, 0xd4, 0x74, 0x0c, 0xa3, + 0x61, 0x3d, 0x23, 0xc4, 0x87, 0x52, 0x5e, 0x8c, 0x15, 0x09, 0x1a, 0x2b, 0x44, 0x91, 0x7a, 0x46, + 0x88, 0xab, 0xa4, 0xbc, 0x14, 0x2b, 0x12, 0xb4, 0x4e, 0x88, 0xbe, 0x64, 0xf4, 0x72, 0x8d, 0x54, + 0x3e, 0x06, 0x3c, 0xd4, 0xdd, 0xbd, 0xdd, 0xe6, 0xfa, 0xb4, 0x5e, 0x2e, 0x96, 0x6f, 0x75, 0xbf, + 0x07, 0x55, 0x5e, 0x96, 0x87, 0x70, 0x37, 0x3a, 0x3a, 0x84, 0xbb, 0xde, 0xa5, 0xbe, 0x12, 0x79, + 0x26, 0xa1, 0xbc, 0x22, 0x4f, 0x71, 0x12, 0x92, 0x4e, 0x71, 0xd1, 0x47, 0x15, 0x92, 0xff, 0xbf, + 0xf2, 0x71, 0x79, 0x8a, 0x13, 0x71, 0x74, 0x8a, 0x93, 0xde, 0x0a, 0x4c, 0xc7, 0xdc, 0xd2, 0x95, + 0x57, 0xe5, 0x29, 0x2e, 0x82, 0xa6, 0x53, 0x5c, 0xd4, 0x91, 0xfd, 0x95, 0x88, 0x77, 0xb6, 0xf2, + 0x5a, 0x72, 0xfb, 0x01, 0x29, 0xb6, 0x9f, 0xf9, 0x72, 0x6b, 0xc9, 0x6e, 0xc6, 0x4a, 0x49, 0x1e, + 0xbf, 0x49, 0x34, 0x74, 0xfc, 0x26, 0xba, 0x28, 0x2f, 0x25, 0xe6, 0x39, 0x55, 0xa6, 0x7a, 0x6c, + 0x1c, 0x42, 0x53, 0x24, 0x29, 0x43, 0xaa, 0xb8, 0x47, 0x66, 0x1b, 0xa1, 0xe9, 0x2e, 0x7b, 0x64, + 0x7f, 0x1b, 0x14, 0xa1, 0xa7, 0xb3, 0x6b, 0xec, 0x5a, 0x4e, 0x29, 0xcb, 0xb3, 0x6b, 0x8c, 0x80, + 0xce, 0xae, 0xf1, 0xcb, 0xbc, 0x59, 0x54, 0xe0, 0x5a, 0xc4, 0x6e, 0x1b, 0x4d, 0x6b, 0x4d, 0x99, + 0x89, 0x78, 0xf9, 0x45, 0xf0, 0x74, 0x76, 0x8a, 0xc2, 0x60, 0xbd, 0x66, 0xb0, 0xe9, 0xa6, 0xd9, + 0x5e, 0xb1, 0x75, 0xc7, 0xa8, 0x11, 0xcb, 0x50, 0x66, 0x23, 0xeb, 0x75, 0x02, 0x0d, 0xac, 0xd7, + 0x09, 0x70, 0x78, 0xe3, 0x1a, 0x81, 0x6b, 0xa4, 0x41, 0xcc, 0xfb, 0x44, 0xb9, 0x05, 0x6c, 0x8b, + 0xdd, 0xd8, 0x72, 0xb2, 0xb9, 0x3e, 0xad, 0x1b, 0x07, 0x6a, 0xab, 0x2f, 0x6c, 0xd5, 0xde, 0x98, + 0x0f, 0x3c, 0xdb, 0xab, 0x0e, 0x69, 0xeb, 0x0e, 0x51, 0xe6, 0x64, 0x5b, 0x3d, 0x91, 0x88, 0xda, + 0xea, 0x89, 0x88, 0x38, 0x5b, 0x7f, 0x2c, 0x54, 0x7a, 0xb1, 0x0d, 0x47, 0x44, 0x72, 0x69, 0x3a, + 0x3b, 0xc9, 0x08, 0x2a, 0xa0, 0x79, 0xdb, 0x5a, 0x83, 0x93, 0x8a, 0xd7, 0xe5, 0xd9, 0xa9, 0x3b, + 0x25, 0x9d, 0x9d, 0xba, 0x63, 0xa9, 0xaa, 0xcb, 0x58, 0x36, 0x06, 0x6f, 0xcb, 0xaa, 0x9e, 0x40, + 0x42, 0x55, 0x3d, 0x01, 0x1c, 0x67, 0xa8, 0x11, 0x97, 0x78, 0xca, 0x7c, 0x2f, 0x86, 0x40, 0x12, + 0x67, 0x08, 0xe0, 0x38, 0xc3, 0x59, 0xe2, 0x35, 0xd6, 0x95, 0x85, 0x5e, 0x0c, 0x81, 0x24, 0xce, + 0x10, 0xc0, 0x74, 0xb3, 0x29, 0x83, 0xa7, 0x3a, 0xcd, 0x0d, 0xbf, 0xcf, 0x16, 0xe5, 0xcd, 0x66, + 0x57, 0x42, 0xba, 0xd9, 0xec, 0x8a, 0xc4, 0xdf, 0xb3, 0xe7, 0x6b, 0x63, 0x65, 0x09, 0x2a, 0x9c, + 0x0c, 0xed, 0x82, 0xbd, 0x94, 0x9a, 0xeb, 0xd3, 0xf6, 0x7a, 0x2d, 0xfd, 0xe1, 0xe0, 0x76, 0x47, + 0xa9, 0x42, 0x55, 0x63, 0xc1, 0x59, 0x05, 0x03, 0xcf, 0xf5, 0x69, 0xc1, 0xfd, 0xcf, 0x0b, 0x68, + 0x08, 0x3e, 0xaa, 0x62, 0x99, 0x5e, 0x79, 0x4a, 0x79, 0x43, 0xde, 0x32, 0x09, 0x28, 0xba, 0x65, + 0x12, 0x7e, 0xd2, 0x49, 0x1c, 0x7e, 0xb2, 0x29, 0xa6, 0x3c, 0xa5, 0x68, 0xf2, 0x24, 0x2e, 0x21, + 0xe9, 0x24, 0x2e, 0x01, 0x82, 0x7a, 0xcb, 0x8e, 0xdd, 0x2e, 0x4f, 0x29, 0xb5, 0x84, 0x7a, 0x19, + 0x2a, 0xa8, 0x97, 0xfd, 0x0c, 0xea, 0xad, 0xad, 0x77, 0xbc, 0x32, 0xfd, 0xc6, 0xe5, 0x84, 0x7a, + 0x7d, 0x64, 0x50, 0xaf, 0x0f, 0xa0, 0x53, 0x21, 0x00, 0xaa, 0x8e, 0x4d, 0x27, 0xed, 0xdb, 0x66, + 0xb3, 0xa9, 0xdc, 0x91, 0xa7, 0xc2, 0x28, 0x9e, 0x4e, 0x85, 0x51, 0x18, 0x35, 0x3d, 0x59, 0xab, + 0xc8, 0x4a, 0x67, 0x4d, 0xb9, 0x2b, 0x9b, 0x9e, 0x21, 0x86, 0x9a, 0x9e, 0xe1, 0x2f, 0xd8, 0x5d, + 0xd0, 0x5f, 0x1a, 0x59, 0x75, 0x88, 0xbb, 0xae, 0xdc, 0x8b, 0xec, 0x2e, 0x04, 0x1c, 0xec, 0x2e, + 0x84, 0xdf, 0x78, 0x0d, 0x3d, 0x26, 0x2d, 0x34, 0xbe, 0xcf, 0x5c, 0x8d, 0xe8, 0x4e, 0x63, 0x5d, + 0xf9, 0x04, 0xb0, 0x7a, 0x32, 0x71, 0xa9, 0x92, 0x49, 0xe7, 0xfa, 0xb4, 0x5e, 0x9c, 0x60, 0x5b, + 0xfe, 0xc6, 0x3c, 0x0b, 0x46, 0xa1, 0x55, 0xa7, 0xfd, 0x4d, 0xe8, 0x9b, 0x91, 0x6d, 0x79, 0x9c, + 0x04, 0xb6, 0xe5, 0x71, 0x30, 0x6e, 0xa3, 0x4b, 0x91, 0xad, 0xda, 0x82, 0xde, 0xa4, 0xfb, 0x12, + 0x62, 0x54, 0xf5, 0xc6, 0x06, 0xf1, 0x94, 0x4f, 0x02, 0xef, 0xcb, 0x5d, 0x36, 0x7c, 0x11, 0xea, + 0xb9, 0x3e, 0x6d, 0x17, 0x7e, 0x58, 0x65, 0x99, 0x34, 0x95, 0x4f, 0xc9, 0xe7, 0x9b, 0x14, 0x36, + 0xd7, 0xa7, 0xb1, 0x2c, 0x9b, 0x6f, 0x21, 0xe5, 0x4e, 0x7b, 0xcd, 0xd1, 0x0d, 0xc2, 0x0c, 0x2d, + 0xb0, 0xdd, 0xb8, 0x01, 0xfa, 0x2d, 0xb2, 0x95, 0xd6, 0x8d, 0x8e, 0x5a, 0x69, 0xdd, 0x70, 0x54, + 0x51, 0xa5, 0xb8, 0x8b, 0xca, 0xa7, 0x65, 0x45, 0x95, 0x90, 0x54, 0x51, 0xe5, 0x28, 0x8d, 0x9f, + 0x40, 0x67, 0x83, 0xfd, 0x3c, 0x5f, 0x7f, 0x59, 0xa7, 0x29, 0x6f, 0x01, 0x9f, 0x4b, 0xb1, 0xcb, + 0x00, 0x89, 0x6a, 0xae, 0x4f, 0xeb, 0x52, 0x9e, 0xae, 0xb8, 0xb1, 0x90, 0xc2, 0xdc, 0xbc, 0xf8, + 0x56, 0x79, 0xc5, 0xed, 0x42, 0x46, 0x57, 0xdc, 0x2e, 0xa8, 0x44, 0xe6, 0x5c, 0xa8, 0xfa, 0x2e, + 0xcc, 0x03, 0x99, 0x76, 0xe3, 0x90, 0xc8, 0x9c, 0x5b, 0x6a, 0x2b, 0xbb, 0x30, 0x0f, 0xac, 0xb5, + 0x6e, 0x1c, 0xf0, 0x15, 0x94, 0xab, 0xd5, 0x16, 0xb4, 0x8e, 0xa5, 0x34, 0x22, 0xd7, 0x72, 0x00, + 0x9d, 0xeb, 0xd3, 0x38, 0x9e, 0x9a, 0x41, 0x33, 0x4d, 0xdd, 0xf5, 0xcc, 0x86, 0x0b, 0x23, 0xc6, + 0x1f, 0x21, 0x86, 0x6c, 0x06, 0x25, 0xd1, 0x50, 0x33, 0x28, 0x09, 0x4e, 0xed, 0xc5, 0x69, 0xdd, + 0x75, 0x75, 0xcb, 0x70, 0xf4, 0x29, 0x58, 0x26, 0x48, 0xc4, 0x79, 0x49, 0xc2, 0x52, 0x7b, 0x51, + 0x86, 0xc0, 0xe1, 0xbb, 0x0f, 0xf1, 0xcd, 0x9c, 0xd5, 0xc8, 0xe1, 0x7b, 0x04, 0x0f, 0x87, 0xef, + 0x11, 0x18, 0xd8, 0x9d, 0x3e, 0x4c, 0x23, 0x6b, 0x26, 0xe4, 0xbd, 0x5e, 0x8b, 0xd8, 0x9d, 0x51, + 0x02, 0xb0, 0x3b, 0xa3, 0x40, 0xa9, 0x49, 0xfe, 0x72, 0xbb, 0xde, 0xa5, 0x49, 0xe1, 0x2a, 0x1b, + 0x2b, 0x43, 0xd7, 0xef, 0x70, 0x70, 0x94, 0xb7, 0x2c, 0xbd, 0x65, 0x97, 0xa7, 0x7c, 0xa9, 0x9b, + 0xf2, 0xfa, 0xdd, 0x95, 0x90, 0xae, 0xdf, 0x5d, 0x91, 0x74, 0x76, 0xf5, 0x37, 0x5a, 0xeb, 0xba, + 0x43, 0x8c, 0x20, 0x1b, 0x2c, 0xdb, 0x1a, 0xbe, 0x2d, 0xcf, 0xae, 0x3d, 0x48, 0xe9, 0xec, 0xda, + 0x03, 0x4d, 0x8d, 0xbc, 0x64, 0xb4, 0x46, 0x74, 0x43, 0xd9, 0x90, 0x8d, 0xbc, 0xee, 0x94, 0xd4, + 0xc8, 0xeb, 0x8e, 0xed, 0xfe, 0x39, 0xf7, 0x1c, 0xd3, 0x23, 0x4a, 0x73, 0x2f, 0x9f, 0x03, 0xa4, + 0xdd, 0x3f, 0x07, 0xd0, 0x74, 0x43, 0x18, 0xed, 0x90, 0x96, 0xbc, 0x21, 0x8c, 0x77, 0x43, 0xb4, + 0x04, 0xb5, 0x58, 0xb8, 0x0f, 0x9b, 0x62, 0xc9, 0x16, 0x0b, 0x07, 0x53, 0x8b, 0x25, 0xf4, 0x72, + 0x93, 0x7c, 0xa6, 0x14, 0x5b, 0x5e, 0x43, 0x45, 0x1c, 0x5d, 0x43, 0x25, 0xff, 0xaa, 0x17, 0x24, + 0x87, 0x06, 0xa5, 0x2d, 0x5b, 0x1d, 0x02, 0x8a, 0x5a, 0x1d, 0xa2, 0xeb, 0xc3, 0x34, 0x1a, 0x83, + 0x5b, 0x70, 0xad, 0x13, 0xdc, 0xe3, 0x7c, 0x46, 0xfe, 0xcc, 0x08, 0x9a, 0x7e, 0x66, 0x04, 0x24, + 0x31, 0xe1, 0xd3, 0x96, 0xd3, 0x85, 0x49, 0x78, 0x3e, 0x18, 0x01, 0xe1, 0x79, 0x84, 0x6b, 0xa5, + 0x85, 0xf9, 0x8a, 0x51, 0x15, 0xaf, 0xc8, 0x5c, 0xf9, 0x04, 0x36, 0x4e, 0x31, 0xd7, 0xa7, 0x25, + 0x94, 0xc3, 0x6f, 0xa3, 0x0b, 0x1c, 0xca, 0x1d, 0x94, 0x21, 0xdf, 0x97, 0x11, 0x2c, 0x08, 0x1e, + 0xf0, 0xfd, 0x40, 0x84, 0x6f, 0x22, 0xed, 0x5c, 0x9f, 0xd6, 0x93, 0x57, 0xf7, 0xba, 0xf8, 0xfa, + 0xd0, 0xd9, 0x4b, 0x5d, 0xc1, 0x22, 0xd1, 0x93, 0x57, 0xf7, 0xba, 0xb8, 0xdc, 0xef, 0xef, 0xa5, + 0xae, 0xa0, 0x13, 0x7a, 0xf2, 0xc2, 0x2e, 0x2a, 0xf6, 0xc2, 0x97, 0x9a, 0x4d, 0x65, 0x13, 0xaa, + 0xfb, 0xd0, 0x5e, 0xaa, 0x2b, 0x81, 0xc1, 0xb9, 0x1b, 0x47, 0x3a, 0x4b, 0x2f, 0xb5, 0x89, 0x55, + 0x93, 0x16, 0xa0, 0x07, 0xf2, 0x2c, 0x1d, 0x23, 0xa0, 0xb3, 0x74, 0x0c, 0x48, 0x07, 0x94, 0xe8, + 0x17, 0xa3, 0x6c, 0xc9, 0x03, 0x4a, 0xc4, 0xd1, 0x01, 0x25, 0xf9, 0xd0, 0x2c, 0xa1, 0x53, 0x4b, + 0x1b, 0x9e, 0xee, 0x5b, 0x90, 0x2e, 0xef, 0xca, 0x77, 0x22, 0x97, 0x4c, 0x71, 0x12, 0xb8, 0x64, + 0x8a, 0x83, 0xe9, 0x18, 0xa1, 0xe0, 0xda, 0x96, 0xd5, 0x98, 0xd5, 0xcd, 0x66, 0xc7, 0x21, 0xca, + 0x9f, 0x93, 0xc7, 0x48, 0x04, 0x4d, 0xc7, 0x48, 0x04, 0x44, 0x17, 0x68, 0x0a, 0x2a, 0xb9, 0xae, + 0xb9, 0x66, 0xf1, 0x7d, 0x65, 0xa7, 0xe9, 0x29, 0x7f, 0x5e, 0x5e, 0xa0, 0x93, 0x68, 0xe8, 0x02, + 0x9d, 0x04, 0x87, 0x53, 0xa7, 0x84, 0x5c, 0x78, 0xca, 0x5f, 0x88, 0x9c, 0x3a, 0x25, 0xd0, 0xc0, + 0xa9, 0x53, 0x52, 0x1e, 0xbd, 0x59, 0x54, 0x60, 0x36, 0xd9, 0xbc, 0x19, 0xdc, 0x55, 0xff, 0x45, + 0x79, 0x7d, 0x8c, 0xe2, 0xe9, 0xfa, 0x18, 0x85, 0xc9, 0x7c, 0x78, 0x17, 0xfc, 0xa5, 0x6e, 0x7c, + 0x02, 0xf9, 0xc7, 0xca, 0xe0, 0x5b, 0x22, 0x1f, 0x3e, 0x52, 0xbe, 0x2d, 0xd5, 0x8d, 0x51, 0x30, + 0x3c, 0x62, 0x85, 0x64, 0x46, 0x1a, 0xb9, 0x6f, 0x92, 0x4d, 0xe5, 0xb3, 0x5d, 0x19, 0x31, 0x02, + 0x99, 0x11, 0x83, 0xe1, 0x37, 0xd1, 0xd9, 0x10, 0xb6, 0x40, 0x5a, 0x2b, 0xc1, 0xcc, 0xf4, 0xed, + 0x29, 0xd9, 0x0c, 0x4e, 0x26, 0xa3, 0x66, 0x70, 0x32, 0x26, 0x89, 0x35, 0x17, 0xdd, 0x5f, 0xde, + 0x85, 0x75, 0x20, 0xc1, 0x2e, 0x0c, 0x92, 0x58, 0x73, 0x69, 0x7e, 0xc7, 0x2e, 0xac, 0x03, 0x99, + 0x76, 0x61, 0x80, 0x3f, 0x97, 0x42, 0x97, 0x93, 0x51, 0xa5, 0x66, 0x73, 0xd6, 0x76, 0x42, 0x9c, + 0xf2, 0x9d, 0x29, 0xf9, 0xa0, 0x61, 0x6f, 0xc5, 0xe6, 0xfa, 0xb4, 0x3d, 0x56, 0x80, 0x3f, 0x8e, + 0x46, 0x4a, 0x1d, 0xc3, 0xf4, 0xe0, 0xe2, 0x8d, 0x1a, 0xce, 0xdf, 0x95, 0x8a, 0x6c, 0x71, 0x44, + 0x2c, 0x6c, 0x71, 0x44, 0x00, 0x7e, 0x1d, 0x8d, 0xd7, 0x48, 0xa3, 0xe3, 0x98, 0xde, 0x96, 0x06, + 0x79, 0x0e, 0x29, 0x8f, 0xef, 0x4e, 0xc9, 0x93, 0x58, 0x8c, 0x82, 0x4e, 0x62, 0x31, 0x20, 0xbe, + 0xdb, 0x25, 0x1b, 0x9e, 0xf2, 0x3d, 0xa9, 0x9e, 0xd7, 0xf2, 0x41, 0x5f, 0x76, 0x49, 0xa6, 0x57, + 0x4d, 0xcc, 0x2e, 0xa6, 0x7c, 0x2e, 0xd5, 0xe3, 0x1a, 0x5d, 0x98, 0xe1, 0x12, 0x12, 0x93, 0x55, + 0x13, 0xf3, 0x47, 0x29, 0xdf, 0x9b, 0xea, 0x71, 0xed, 0x1d, 0x72, 0x4c, 0x4a, 0x3d, 0xf5, 0x9c, + 0x98, 0x50, 0x5a, 0xf9, 0x2b, 0xa9, 0xb8, 0xab, 0x48, 0x50, 0x5e, 0xcc, 0x3c, 0xfd, 0x1c, 0x73, + 0xcd, 0xe3, 0xc5, 0x3e, 0x9f, 0x8a, 0xfb, 0xe6, 0x85, 0xc5, 0xc2, 0x5f, 0x98, 0xa0, 0x89, 0x99, + 0x07, 0x1e, 0x71, 0x2c, 0xbd, 0x09, 0xdd, 0x59, 0xf3, 0x6c, 0x47, 0x5f, 0x23, 0x33, 0x96, 0xbe, + 0xd2, 0x24, 0xca, 0xf7, 0xa5, 0x64, 0x0b, 0xb6, 0x3b, 0x29, 0xb5, 0x60, 0xbb, 0x63, 0xf1, 0x3a, + 0x7a, 0x2c, 0x09, 0x5b, 0x36, 0x5d, 0xa8, 0xe7, 0x0b, 0x29, 0xd9, 0x84, 0xed, 0x41, 0x4b, 0x4d, + 0xd8, 0x1e, 0x68, 0x7c, 0x43, 0xc8, 0xb6, 0xac, 0xfc, 0xd5, 0x88, 0x33, 0x64, 0x80, 0x99, 0xeb, + 0xd3, 0x84, 0xa4, 0xcc, 0x37, 0x84, 0xac, 0xc0, 0xca, 0x17, 0xe3, 0x65, 0xc2, 0xcb, 0xa7, 0x30, + 0x79, 0xf0, 0x0d, 0x21, 0x1f, 0xb2, 0xf2, 0xd7, 0xe2, 0x65, 0xc2, 0x3b, 0xae, 0x30, 0x6d, 0xf2, + 0x9b, 0xe8, 0x2c, 0xab, 0x71, 0x61, 0xb6, 0x44, 0xed, 0xb6, 0xe9, 0x75, 0xbd, 0xd9, 0x24, 0xd6, + 0x1a, 0x51, 0xbe, 0x14, 0x99, 0x49, 0x92, 0xc9, 0xe8, 0x4c, 0x92, 0x8c, 0xc1, 0xdf, 0x82, 0xce, + 0xdd, 0xd5, 0x9b, 0xa6, 0x11, 0xe2, 0xfc, 0x94, 0x44, 0xca, 0xf7, 0xa7, 0xe4, 0xdd, 0x74, 0x17, + 0x3a, 0xba, 0x9b, 0xee, 0x82, 0xc2, 0x0b, 0x08, 0xc3, 0x32, 0x1a, 0xcc, 0x16, 0x74, 0x7d, 0x56, + 0xfe, 0x7a, 0x4a, 0xb6, 0x53, 0xe3, 0x24, 0xd4, 0x4e, 0x8d, 0x43, 0x71, 0xbd, 0x7b, 0xd4, 0x49, + 0xe5, 0x07, 0x52, 0xf2, 0x69, 0x4d, 0x37, 0xc2, 0xb9, 0x3e, 0xad, 0x7b, 0xe8, 0xca, 0x5b, 0xa8, + 0x50, 0xab, 0x56, 0x66, 0x67, 0x67, 0x6a, 0x77, 0x2b, 0xe5, 0x8a, 0xeb, 0x76, 0x88, 0xa1, 0xfc, + 0x60, 0x64, 0xc5, 0x8a, 0x12, 0xd0, 0x15, 0x2b, 0x0a, 0xc3, 0x35, 0x74, 0x9a, 0x0a, 0xa2, 0xea, + 0x90, 0x55, 0xe2, 0x10, 0xab, 0xe1, 0x0f, 0xcb, 0x1f, 0x4e, 0xc9, 0x86, 0x42, 0x12, 0x11, 0x35, + 0x14, 0x92, 0xe0, 0x78, 0x03, 0x5d, 0x88, 0x1e, 0xe6, 0x4c, 0xdb, 0xd6, 0xaa, 0xb9, 0xc6, 0x99, + 0xff, 0x48, 0x2a, 0x62, 0xcf, 0xf6, 0x20, 0x06, 0x7b, 0xb6, 0x07, 0x1e, 0x5b, 0xe8, 0x22, 0x3f, + 0x19, 0xe1, 0x3e, 0x93, 0xd1, 0xda, 0xfe, 0x06, 0xab, 0xed, 0x83, 0xa1, 0x4f, 0x5f, 0x0f, 0xea, + 0xb9, 0x3e, 0xad, 0x37, 0x3b, 0xaa, 0x2a, 0xf1, 0xf0, 0x88, 0xca, 0x8f, 0xa6, 0x92, 0x9d, 0x4a, + 0x24, 0x4f, 0xe3, 0xa4, 0xb8, 0x8a, 0x6f, 0x76, 0x0b, 0xee, 0xa7, 0xfc, 0x58, 0x64, 0xc8, 0x24, + 0x93, 0xd1, 0x21, 0xd3, 0x25, 0x3a, 0xe0, 0x73, 0x08, 0xd5, 0xda, 0xba, 0x65, 0xc1, 0xe9, 0xa6, + 0xf2, 0x37, 0x23, 0x33, 0x66, 0x88, 0x02, 0x7f, 0xd9, 0xe0, 0xd7, 0xd4, 0x00, 0xea, 0x07, 0x73, + 0x59, 0xfd, 0xf1, 0x14, 0x1a, 0xae, 0x79, 0x0e, 0xd1, 0x5b, 0xfc, 0xf5, 0xcd, 0x04, 0xca, 0x33, + 0xbf, 0x93, 0x4a, 0x99, 0x3f, 0xd6, 0x0b, 0x7e, 0xe3, 0xcb, 0x68, 0x74, 0x5e, 0x77, 0x3d, 0x28, + 0x59, 0xb1, 0x0c, 0xf2, 0x00, 0x7c, 0xae, 0x33, 0x5a, 0x04, 0x8a, 0xe7, 0x19, 0x1d, 0x2b, 0x07, + 0xcf, 0x1e, 0x33, 0xbb, 0x3e, 0x3a, 0xc9, 0xbf, 0xbb, 0x5d, 0xec, 0x83, 0x37, 0x26, 0x91, 0xb2, + 0xea, 0xd7, 0x52, 0x28, 0xe6, 0x11, 0x73, 0xf0, 0x17, 0x22, 0x4b, 0x68, 0x2c, 0xf2, 0xd4, 0x96, + 0x3b, 0x8e, 0xef, 0xf1, 0x25, 0x6e, 0xb4, 0x34, 0xfe, 0x50, 0xe0, 0xb0, 0x7c, 0x47, 0x9b, 0xe7, + 0x0f, 0x8a, 0x06, 0x76, 0xb6, 0x8b, 0x99, 0x8e, 0xd3, 0xd4, 0x04, 0x14, 0x77, 0x78, 0xff, 0xf9, + 0x42, 0xf8, 0x8e, 0x10, 0x5f, 0xe6, 0xcf, 0x88, 0x53, 0xe1, 0x33, 0xa4, 0x48, 0x4a, 0x01, 0xf6, + 0x6c, 0xf8, 0xe3, 0x68, 0xb8, 0xd2, 0x6a, 0x13, 0xc7, 0xb5, 0x2d, 0xdd, 0xb3, 0xfd, 0xd4, 0x65, + 0xf0, 0x44, 0xc5, 0x14, 0xe0, 0xe2, 0xb3, 0x09, 0x91, 0x1e, 0x5f, 0xf5, 0xe3, 0x4f, 0x66, 0xe0, + 0x05, 0xe7, 0xa9, 0x84, 0x2c, 0xd3, 0x7e, 0xae, 0xe8, 0xab, 0xa8, 0xff, 0x8e, 0xab, 0x83, 0x6b, + 0x7b, 0x40, 0xda, 0xa1, 0x00, 0x91, 0x14, 0x28, 0xf0, 0x35, 0x94, 0x83, 0xa3, 0x00, 0x17, 0xe2, + 0xca, 0xf2, 0xc7, 0x51, 0x4d, 0x80, 0x88, 0x4f, 0x51, 0x18, 0x0d, 0xbe, 0x8d, 0x0a, 0xe1, 0x39, + 0x27, 0x24, 0xdb, 0xf3, 0x23, 0x49, 0x41, 0x78, 0xff, 0x8d, 0x00, 0xc7, 0xb2, 0xf4, 0x89, 0x2c, + 0x62, 0x05, 0xf1, 0x1c, 0x1a, 0x0b, 0x61, 0x54, 0x44, 0x7e, 0x04, 0x3b, 0x48, 0x6f, 0x21, 0xf0, + 0xa2, 0xe2, 0x14, 0x59, 0x45, 0x8b, 0xe1, 0x0a, 0x1a, 0xf0, 0x5f, 0x46, 0xe5, 0x77, 0x55, 0xd2, + 0x53, 0xfc, 0x65, 0xd4, 0x80, 0xf8, 0x26, 0xca, 0x2f, 0x8f, 0x67, 0xd1, 0xa8, 0x66, 0x77, 0x3c, + 0xb2, 0x6c, 0xf3, 0xd9, 0x85, 0x87, 0x38, 0x82, 0x36, 0x39, 0x14, 0x53, 0xf7, 0x6c, 0x3f, 0x3b, + 0x82, 0x18, 0xa5, 0x5f, 0x2e, 0x85, 0x17, 0xd1, 0x78, 0xec, 0x44, 0x58, 0xcc, 0x59, 0x20, 0x7c, + 0x5e, 0x9c, 0x59, 0xbc, 0x28, 0xfe, 0xae, 0x14, 0xca, 0x2d, 0x3b, 0xba, 0xe9, 0xb9, 0xdc, 0x2b, + 0xfe, 0xcc, 0xe4, 0xa6, 0xa3, 0xb7, 0xa9, 0x7e, 0x4c, 0xc2, 0x13, 0xdd, 0xbb, 0x7a, 0xb3, 0x43, + 0xdc, 0xa9, 0x7b, 0xf4, 0xeb, 0xfe, 0xc3, 0x76, 0xf1, 0x63, 0xfb, 0xc8, 0xfe, 0x7d, 0x3d, 0xe0, + 0xc4, 0x6a, 0xa0, 0x2a, 0xe0, 0xc1, 0x5f, 0xa2, 0x0a, 0x30, 0x1c, 0x5e, 0xa4, 0x56, 0x21, 0x7c, + 0x6a, 0xa9, 0xdd, 0xe6, 0x2e, 0xf6, 0x82, 0x51, 0xe8, 0x63, 0x98, 0x62, 0x07, 0x02, 0xd3, 0xdb, + 0x62, 0xca, 0x46, 0x81, 0x03, 0xd5, 0x82, 0x65, 0xde, 0x22, 0x5f, 0x4c, 0x23, 0xa1, 0xc4, 0xfd, + 0xc6, 0x26, 0x08, 0x29, 0x5a, 0x0c, 0xaf, 0xa0, 0x31, 0xce, 0x37, 0x88, 0x39, 0x34, 0x2a, 0xcf, + 0x0a, 0x11, 0x34, 0x53, 0xda, 0xa0, 0x8d, 0x06, 0x07, 0x8b, 0x75, 0x44, 0x4a, 0xe0, 0xa9, 0x30, + 0xdc, 0x36, 0xe4, 0x87, 0x54, 0xc6, 0x40, 0x63, 0x2f, 0xec, 0x6c, 0x17, 0x15, 0xbf, 0x3c, 0x4b, + 0x2b, 0x99, 0x94, 0x3c, 0x02, 0x8a, 0x88, 0x3c, 0x98, 0xd6, 0x17, 0x12, 0x78, 0x44, 0x75, 0x5e, + 0x2e, 0x82, 0xa7, 0xd1, 0x48, 0xe0, 0xe1, 0x77, 0xe7, 0x4e, 0xa5, 0x0c, 0x3e, 0xfc, 0x3c, 0x11, + 0x62, 0x24, 0x9c, 0x91, 0xc8, 0x44, 0x2a, 0x83, 0x9f, 0x45, 0x79, 0xe6, 0x23, 0x5f, 0x61, 0x4e, + 0xfd, 0xfe, 0x4b, 0x6a, 0x80, 0xd5, 0x4d, 0xb1, 0xc7, 0x02, 0x42, 0xfc, 0x0a, 0x1a, 0x2a, 0xdd, + 0xab, 0xd1, 0x79, 0xa6, 0xa4, 0x2d, 0xba, 0xca, 0xa9, 0x30, 0x8e, 0x1c, 0xe4, 0x0f, 0xb1, 0x9b, + 0xa4, 0xae, 0x3b, 0xd2, 0xe4, 0x21, 0xd2, 0xe3, 0x19, 0x34, 0x2a, 0x5d, 0x12, 0xba, 0xca, 0x69, + 0xe0, 0xc0, 0x52, 0x38, 0x02, 0xa6, 0xce, 0xb3, 0x88, 0x4a, 0x49, 0x52, 0xe4, 0x42, 0x54, 0x6b, + 0xa8, 0x9d, 0xdd, 0x6c, 0xda, 0x9b, 0x1a, 0x31, 0xa9, 0x89, 0x04, 0x2f, 0x02, 0xf2, 0x4c, 0x6b, + 0x0c, 0x8e, 0xaa, 0x3b, 0x0c, 0x27, 0xa5, 0xb0, 0x91, 0x8b, 0xe1, 0xb7, 0x11, 0x86, 0x28, 0x5e, + 0xc4, 0xf0, 0xcf, 0x8c, 0x2a, 0x65, 0x57, 0x39, 0x0b, 0xa1, 0x0a, 0x70, 0x34, 0xd0, 0x48, 0xa5, + 0x3c, 0x75, 0x99, 0x4f, 0x1f, 0x97, 0x74, 0x56, 0xaa, 0x1e, 0x64, 0xf0, 0x34, 0x0d, 0xb1, 0xc5, + 0x09, 0x5c, 0xf1, 0x26, 0x3a, 0x57, 0x75, 0xc8, 0x7d, 0xd3, 0xee, 0xb8, 0xfe, 0xf2, 0xe1, 0xcf, + 0x5b, 0xe7, 0x76, 0x9d, 0xb7, 0x9e, 0xe0, 0x15, 0x9f, 0x69, 0x3b, 0xe4, 0x7e, 0xdd, 0x7f, 0xa0, + 0x2e, 0xbd, 0xec, 0xec, 0xc6, 0x9d, 0x8a, 0xab, 0xf4, 0x4e, 0xc7, 0x21, 0x1c, 0x6e, 0x12, 0x57, + 0x51, 0xc2, 0xa9, 0x56, 0xa7, 0x28, 0x9f, 0xa3, 0x29, 0xa9, 0x6e, 0xb4, 0x18, 0xd6, 0x10, 0xbe, + 0x35, 0xed, 0x9f, 0x1f, 0x96, 0x1a, 0x2c, 0x9c, 0xb5, 0x72, 0x1e, 0x98, 0xa9, 0x54, 0x2c, 0x6b, + 0x8d, 0x20, 0x58, 0x45, 0x5d, 0xe7, 0x78, 0x51, 0x2c, 0xf1, 0xd2, 0x78, 0x1e, 0x15, 0xaa, 0x0e, + 0x98, 0x42, 0xb7, 0xc9, 0x56, 0xd5, 0x6e, 0x9a, 0x8d, 0x2d, 0x78, 0x98, 0xc0, 0xa7, 0xca, 0x36, + 0xc3, 0xd5, 0x37, 0xc8, 0x56, 0xbd, 0x0d, 0x58, 0x71, 0x59, 0x89, 0x96, 0x14, 0x1f, 0x8f, 0x3f, + 0xb6, 0xb7, 0xc7, 0xe3, 0x04, 0x15, 0xf8, 0xe9, 0xe3, 0x03, 0x8f, 0x58, 0x74, 0xa9, 0x77, 0xf9, + 0x23, 0x04, 0x25, 0x72, 0x5a, 0x19, 0xe0, 0x79, 0x3a, 0x1b, 0x36, 0xca, 0x48, 0x00, 0x16, 0x1b, + 0x16, 0x2d, 0xa2, 0x7e, 0x21, 0x23, 0x4e, 0x9d, 0xf8, 0x02, 0xca, 0x0a, 0xb1, 0xcb, 0xe0, 0xcd, + 0x29, 0xc4, 0x79, 0xc8, 0xf2, 0x07, 0xed, 0x83, 0xdc, 0xec, 0x08, 0x62, 0x95, 0x41, 0x60, 0x57, + 0x3f, 0xa0, 0x84, 0x69, 0x68, 0x21, 0x01, 0x04, 0xd5, 0x0c, 0xb3, 0xfe, 0x65, 0x84, 0xa0, 0x9a, + 0x61, 0xd6, 0x3f, 0x29, 0xe7, 0xdf, 0x0d, 0x34, 0xe4, 0x5b, 0xcf, 0xe1, 0x9b, 0x6b, 0x08, 0x0a, + 0xe1, 0x27, 0xfe, 0x61, 0x31, 0x27, 0x04, 0x22, 0xfc, 0x12, 0xa4, 0xbe, 0xe2, 0x23, 0x99, 0x1b, + 0x49, 0x30, 0xcb, 0x8b, 0x03, 0x3f, 0x92, 0xfb, 0x8a, 0x53, 0xd3, 0x39, 0x4f, 0xd4, 0x24, 0x3f, + 0x8c, 0x30, 0xcc, 0x79, 0x92, 0xfa, 0x6d, 0x49, 0x79, 0x5b, 0xc5, 0x22, 0x78, 0x09, 0x8d, 0xc7, + 0x94, 0x87, 0xbf, 0xd0, 0x86, 0x84, 0x05, 0x09, 0x9a, 0x27, 0xae, 0xa9, 0xb1, 0xb2, 0xea, 0xb7, + 0xa7, 0x63, 0x2b, 0x06, 0x15, 0x0c, 0xa7, 0x12, 0x3a, 0x07, 0x04, 0xe3, 0xb3, 0x66, 0x82, 0x11, + 0x88, 0xf0, 0x15, 0x94, 0x8f, 0x64, 0xbf, 0x82, 0x18, 0x12, 0x41, 0xea, 0xab, 0x00, 0x8b, 0x6f, + 0x08, 0x81, 0xad, 0x85, 0xc8, 0x06, 0x7e, 0x60, 0x6b, 0x71, 0xc2, 0x0d, 0x42, 0x5c, 0xdf, 0x88, + 0xc4, 0xd0, 0xf3, 0x93, 0x14, 0xc5, 0x57, 0xab, 0x30, 0x42, 0x68, 0x60, 0x2b, 0xf6, 0xef, 0x66, + 0x2b, 0xaa, 0xbf, 0x9a, 0x8a, 0x6b, 0x3f, 0xbe, 0x19, 0x7f, 0xde, 0xcc, 0xf2, 0x13, 0xf9, 0x40, + 0xb1, 0xd6, 0xe0, 0xa1, 0xb3, 0xf4, 0x50, 0x39, 0x7d, 0xe0, 0x87, 0xca, 0x99, 0x7d, 0x3e, 0x54, + 0x56, 0xff, 0x6f, 0xb6, 0xa7, 0x0f, 0xcb, 0x91, 0x04, 0x09, 0x7a, 0x91, 0xee, 0x77, 0x68, 0xed, + 0x25, 0x37, 0x66, 0xb5, 0xb3, 0x2b, 0xfa, 0xba, 0xce, 0x46, 0x8d, 0xab, 0xc9, 0x94, 0x62, 0xb6, + 0x68, 0x78, 0x00, 0x9f, 0x4d, 0xc8, 0x16, 0x1d, 0x4d, 0x31, 0x25, 0x16, 0xc0, 0xcf, 0xa1, 0xc1, + 0x30, 0xef, 0x75, 0xbf, 0x10, 0x4e, 0x21, 0x21, 0xdd, 0x75, 0x48, 0x89, 0x3f, 0x8d, 0x72, 0x52, + 0x8e, 0xb3, 0xeb, 0x7b, 0x70, 0xfa, 0x99, 0x14, 0x83, 0xf4, 0xb0, 0xbd, 0x43, 0x34, 0xbf, 0x19, + 0x67, 0x8a, 0x97, 0xd1, 0xa9, 0xaa, 0x43, 0x0c, 0x70, 0x2f, 0x9b, 0x79, 0xd0, 0x76, 0x78, 0x08, + 0x25, 0x36, 0x80, 0x61, 0xe9, 0x68, 0xfb, 0x68, 0xba, 0xa8, 0x71, 0xbc, 0xc0, 0x28, 0xa9, 0x38, + 0xb5, 0x27, 0x58, 0x4b, 0x6e, 0x93, 0xad, 0x4d, 0xdb, 0x31, 0x58, 0x94, 0x21, 0x6e, 0x4f, 0x70, + 0x41, 0x6f, 0x70, 0x94, 0x68, 0x4f, 0xc8, 0x85, 0x26, 0x5e, 0x44, 0x43, 0x07, 0x0d, 0x74, 0xf3, + 0x73, 0xe9, 0x2e, 0xde, 0xa0, 0x8f, 0x6e, 0x80, 0xe2, 0x20, 0x58, 0x7c, 0x7f, 0x97, 0x60, 0xf1, + 0xdf, 0x48, 0x77, 0x71, 0x75, 0x7d, 0xa4, 0x83, 0x3a, 0x07, 0xc2, 0x90, 0x83, 0x3a, 0x87, 0xf1, + 0xb4, 0x4d, 0x43, 0x13, 0x89, 0x22, 0xe1, 0xdf, 0x73, 0xbb, 0x86, 0x7f, 0xff, 0xc9, 0x4c, 0x2f, + 0x57, 0xe0, 0x13, 0xd9, 0xef, 0x47, 0xf6, 0x37, 0xd0, 0x50, 0x20, 0x59, 0x9e, 0x28, 0x76, 0x24, + 0x08, 0xab, 0xc5, 0xc0, 0x50, 0x46, 0x20, 0xc2, 0x57, 0x59, 0x5b, 0x6b, 0xe6, 0x3b, 0x2c, 0xb4, + 0xcc, 0x08, 0x0f, 0x1a, 0xa2, 0x7b, 0x7a, 0xdd, 0x35, 0xdf, 0x21, 0x5a, 0x80, 0x56, 0xff, 0x69, + 0x3a, 0xd1, 0x9f, 0xfa, 0xa4, 0x8f, 0xf6, 0xd1, 0x47, 0x09, 0x42, 0x64, 0x9e, 0xe0, 0x27, 0x42, + 0xdc, 0x87, 0x10, 0xff, 0x30, 0x9d, 0xe8, 0x37, 0x7f, 0x22, 0xc4, 0xfd, 0xcc, 0x16, 0xd7, 0xd0, + 0xa0, 0x66, 0x6f, 0xba, 0x90, 0xeb, 0x89, 0xcf, 0x15, 0x30, 0x51, 0x3b, 0xf6, 0xa6, 0xcb, 0xf2, + 0x60, 0x69, 0x21, 0x81, 0xfa, 0x47, 0xe9, 0x1e, 0x2f, 0x0b, 0x4e, 0x04, 0xff, 0xcd, 0x5c, 0x22, + 0x7f, 0x31, 0x2d, 0xbd, 0x5c, 0x78, 0xa4, 0xb3, 0xa3, 0xd4, 0x1a, 0xeb, 0xa4, 0xa5, 0x47, 0xb3, + 0xa3, 0xb8, 0x00, 0xe5, 0xc1, 0xd5, 0x43, 0x12, 0xf5, 0xcb, 0xe9, 0xc8, 0xd3, 0x8d, 0x13, 0xd9, + 0xed, 0x59, 0x76, 0x81, 0xd6, 0xf1, 0xd7, 0x28, 0x27, 0x92, 0xdb, 0xab, 0xe4, 0xbe, 0x27, 0x1d, + 0x79, 0xb8, 0xf3, 0xe8, 0x26, 0x4a, 0xf8, 0x72, 0x3a, 0xfe, 0x08, 0xe9, 0xd1, 0xd5, 0xa4, 0x6b, + 0x68, 0x90, 0xcb, 0x21, 0x58, 0x2a, 0xd8, 0xbc, 0xcf, 0x80, 0x70, 0x80, 0x1a, 0x10, 0xa8, 0xdf, + 0x99, 0x46, 0xf2, 0x83, 0xaa, 0x47, 0x54, 0x87, 0x7e, 0x31, 0x2d, 0x3f, 0x25, 0x7b, 0x74, 0xf5, + 0x67, 0x12, 0xa1, 0x5a, 0x67, 0xa5, 0xc1, 0x23, 0x91, 0xf5, 0x0b, 0x27, 0xf0, 0x01, 0x54, 0x13, + 0x28, 0xd4, 0x3f, 0x4d, 0x27, 0xbe, 0x6f, 0x7b, 0x74, 0x05, 0xf8, 0x2c, 0x9c, 0x8a, 0x37, 0xac, + 0x70, 0x22, 0x87, 0x43, 0x48, 0x3a, 0xfe, 0x62, 0x31, 0x5d, 0x7d, 0x42, 0xfc, 0xd1, 0x04, 0x73, + 0x0d, 0xc2, 0xaf, 0x26, 0x26, 0x21, 0x16, 0x0d, 0xb7, 0x7f, 0x99, 0xde, 0xed, 0x39, 0xe0, 0xa3, + 0xbc, 0xaa, 0x0e, 0x54, 0xf5, 0x2d, 0x08, 0x5b, 0x43, 0x7b, 0x62, 0x98, 0x45, 0x1c, 0x6d, 0x33, + 0x90, 0x78, 0x23, 0xc6, 0xa9, 0xd4, 0x3f, 0xe8, 0x4f, 0x7e, 0x8b, 0xf6, 0xe8, 0x8a, 0xf0, 0x02, + 0xca, 0x56, 0x75, 0x6f, 0x9d, 0x6b, 0x32, 0xdc, 0xd6, 0xb5, 0x75, 0x6f, 0x5d, 0x03, 0x28, 0xbe, + 0x8a, 0xf2, 0x9a, 0xbe, 0x29, 0x26, 0xc8, 0x84, 0x83, 0x1d, 0x47, 0xdf, 0xe4, 0x19, 0xb8, 0x03, + 0x34, 0x56, 0x83, 0x68, 0xc4, 0xec, 0xe4, 0x1b, 0x42, 0x79, 0xb2, 0x68, 0xc4, 0x41, 0x0c, 0xe2, + 0x0b, 0x28, 0x3b, 0x65, 0x1b, 0x5b, 0xe0, 0xcc, 0x32, 0xcc, 0x2a, 0x5b, 0xb1, 0x8d, 0x2d, 0x0d, + 0xa0, 0xf8, 0x73, 0x29, 0x34, 0x30, 0x47, 0x74, 0x83, 0x8e, 0x90, 0xc1, 0x5e, 0xbe, 0x20, 0x9f, + 0x78, 0x38, 0xbe, 0x20, 0xe3, 0xeb, 0xac, 0x32, 0x51, 0x51, 0x78, 0xfd, 0xf8, 0x16, 0xca, 0x4f, + 0xeb, 0x1e, 0x59, 0xb3, 0x9d, 0x2d, 0xf0, 0x6e, 0x19, 0x0d, 0x3d, 0xa2, 0x25, 0xfd, 0xf1, 0x89, + 0xd8, 0xcd, 0x58, 0x83, 0xff, 0xd2, 0x82, 0xc2, 0x54, 0x2c, 0x3c, 0x4b, 0xc9, 0x50, 0x28, 0x16, + 0x96, 0x8e, 0x24, 0x48, 0x46, 0x12, 0x1c, 0x2b, 0x0f, 0x27, 0x1f, 0x2b, 0x83, 0xf5, 0x08, 0x1e, + 0x70, 0x10, 0x03, 0x78, 0x04, 0x16, 0x7d, 0x66, 0x3d, 0x02, 0x14, 0x42, 0x00, 0x6b, 0x02, 0x89, + 0xfa, 0xf5, 0x7e, 0x94, 0xf8, 0x72, 0xe5, 0x44, 0xc9, 0x4f, 0x94, 0x3c, 0x54, 0xf2, 0x72, 0x4c, + 0xc9, 0x27, 0xe2, 0x6f, 0xa1, 0xde, 0xa3, 0x1a, 0xfe, 0x43, 0xd9, 0xd8, 0x4b, 0xca, 0x47, 0x7b, + 0x77, 0x19, 0x4a, 0xaf, 0x7f, 0x57, 0xe9, 0x05, 0x03, 0x22, 0xb7, 0xeb, 0x80, 0x18, 0xd8, 0xeb, + 0x80, 0xc8, 0x77, 0x1d, 0x10, 0xa1, 0x82, 0x0c, 0x76, 0x55, 0x90, 0x0a, 0x1f, 0x34, 0xa8, 0x77, + 0x7c, 0xf9, 0x0b, 0x3b, 0xdb, 0xc5, 0x51, 0x3a, 0x9a, 0x12, 0x23, 0xcb, 0x03, 0x0b, 0xf5, 0x6b, + 0xd9, 0x1e, 0xcf, 0x9f, 0x8f, 0x44, 0x47, 0x9e, 0x45, 0x99, 0x52, 0xbb, 0xcd, 0xf5, 0xe3, 0x94, + 0xf0, 0xf2, 0xba, 0x4b, 0x29, 0x4a, 0x8d, 0x5f, 0x42, 0x99, 0xd2, 0xbd, 0x5a, 0x34, 0x88, 0x73, + 0xe9, 0x5e, 0x8d, 0x7f, 0x49, 0xd7, 0xb2, 0xf7, 0x6a, 0xf8, 0xe5, 0x30, 0x9a, 0xd2, 0x7a, 0xc7, + 0xda, 0xe0, 0x1b, 0x45, 0xee, 0x04, 0xeb, 0x7b, 0xda, 0x34, 0x28, 0x8a, 0x6e, 0x17, 0x23, 0xb4, + 0x11, 0x6d, 0xca, 0xed, 0x5d, 0x9b, 0x06, 0x76, 0xd5, 0xa6, 0xfc, 0x5e, 0xb5, 0x69, 0x70, 0x0f, + 0xda, 0x84, 0x76, 0xd5, 0xa6, 0xa1, 0xc3, 0x6b, 0x53, 0x1b, 0x4d, 0xc4, 0x43, 0x56, 0x04, 0x1a, + 0xa1, 0x21, 0x1c, 0xc7, 0x72, 0xc7, 0x12, 0xb8, 0xfa, 0xef, 0x30, 0x6c, 0x9d, 0x65, 0x13, 0x8a, + 0xe6, 0xe2, 0xd1, 0x12, 0x4a, 0xab, 0x3f, 0x97, 0xee, 0x1e, 0x69, 0xe3, 0x78, 0x4e, 0x71, 0xdf, + 0x9a, 0x28, 0xa5, 0xac, 0xfc, 0xf2, 0xa9, 0xbb, 0x94, 0x23, 0x6c, 0x93, 0x64, 0xf6, 0xd5, 0x54, + 0xb7, 0xf0, 0x1f, 0x87, 0x92, 0xd8, 0x07, 0xe3, 0xce, 0x6a, 0xe0, 0x3d, 0xef, 0xca, 0x5e, 0x6a, + 0xd1, 0xe4, 0x34, 0x99, 0x03, 0x26, 0xa7, 0xf9, 0xd5, 0x14, 0x3a, 0x75, 0xbb, 0xb3, 0x42, 0xb8, + 0x73, 0x5a, 0xd0, 0x8c, 0xb7, 0x11, 0xa2, 0x60, 0xee, 0xc4, 0x92, 0x02, 0x27, 0x96, 0x0f, 0x8b, + 0xa1, 0x3b, 0x22, 0x05, 0x26, 0x43, 0x6a, 0xe6, 0xc0, 0x72, 0xd1, 0x77, 0xb1, 0xdc, 0xe8, 0xac, + 0x90, 0x7a, 0xcc, 0x93, 0x45, 0xe0, 0x3e, 0xf1, 0x0a, 0x73, 0x5e, 0x3f, 0xa8, 0xd3, 0xc8, 0xcf, + 0xa4, 0xbb, 0x46, 0x4b, 0x39, 0x12, 0xdd, 0x15, 0x93, 0xec, 0x65, 0x0e, 0x98, 0x64, 0xef, 0x53, + 0x89, 0xbd, 0xc2, 0xf5, 0xf7, 0xb1, 0x1e, 0xfd, 0x10, 0xe1, 0x98, 0xc4, 0x25, 0x59, 0x60, 0x47, + 0x38, 0xd8, 0xdf, 0xf3, 0x02, 0xfb, 0xad, 0x54, 0xd7, 0xa8, 0x36, 0xc7, 0x55, 0x60, 0xea, 0x7f, + 0xcd, 0xf8, 0xc1, 0x74, 0x0e, 0xf5, 0x09, 0xd7, 0xd0, 0x20, 0xcf, 0x18, 0x20, 0xfb, 0xd6, 0xf2, + 0xa3, 0x3c, 0x38, 0x1a, 0x0e, 0x08, 0xe8, 0x32, 0xef, 0x07, 0xfb, 0x08, 0xd2, 0x19, 0xc1, 0x32, + 0x6f, 0x72, 0x28, 0xa5, 0x17, 0x48, 0xe8, 0x42, 0x3e, 0xf3, 0xc0, 0xf4, 0xc0, 0x2a, 0xa0, 0x7d, + 0x99, 0x61, 0x0b, 0x39, 0x79, 0x60, 0x7a, 0xcc, 0x26, 0x08, 0xd0, 0x74, 0x91, 0x16, 0xd2, 0x86, + 0xf3, 0x45, 0xda, 0xe5, 0xa9, 0x4b, 0xf8, 0x63, 0xae, 0x6b, 0x68, 0x90, 0x3b, 0xac, 0x72, 0x37, + 0x13, 0xde, 0x5a, 0xee, 0xe2, 0x0a, 0xad, 0x0d, 0x08, 0x28, 0x47, 0x8d, 0xac, 0x85, 0x8e, 0x75, + 0xc0, 0xd1, 0x01, 0x88, 0xc6, 0x31, 0xf8, 0x06, 0x1a, 0xad, 0x79, 0xba, 0x65, 0xe8, 0x8e, 0xb1, + 0xd4, 0xf1, 0xda, 0x1d, 0x4f, 0x34, 0x4a, 0x5d, 0xcf, 0xb0, 0x3b, 0x9e, 0x16, 0xa1, 0xc0, 0x1f, + 0x81, 0x84, 0xff, 0x00, 0x99, 0x71, 0x1c, 0xdb, 0x11, 0x2d, 0x0f, 0xd7, 0x33, 0x88, 0xe3, 0x68, + 0x32, 0x01, 0xfe, 0x28, 0x1a, 0xa9, 0x58, 0xf7, 0xed, 0x06, 0x8b, 0x12, 0xac, 0xcd, 0x73, 0x3b, + 0x04, 0x1e, 0x48, 0x99, 0x01, 0xa2, 0xde, 0x71, 0x9a, 0x9a, 0x4c, 0xa8, 0xee, 0xa4, 0xe3, 0x31, + 0x87, 0x1e, 0xdd, 0x4d, 0xcb, 0x55, 0xd9, 0x99, 0x0e, 0x3c, 0x48, 0xc1, 0x20, 0x14, 0x7d, 0x79, + 0x99, 0x5d, 0x78, 0x03, 0xe5, 0x6f, 0x93, 0x2d, 0xe6, 0xf7, 0x99, 0x0b, 0x5d, 0x85, 0x37, 0x38, + 0x4c, 0x3c, 0x71, 0xf5, 0xe9, 0xd4, 0xaf, 0xa4, 0xe3, 0xd1, 0x94, 0x1e, 0x5d, 0x61, 0x7f, 0x04, + 0x0d, 0x80, 0x28, 0x2b, 0xfe, 0x91, 0x3f, 0x08, 0x10, 0xc4, 0x2d, 0x7b, 0x20, 0xfb, 0x64, 0xea, + 0x4f, 0xe4, 0xa2, 0x21, 0xb6, 0x1e, 0x5d, 0xe9, 0x7d, 0x0c, 0x0d, 0x4d, 0xdb, 0x96, 0x6b, 0xba, + 0x1e, 0xb1, 0x1a, 0xbe, 0xc2, 0x9e, 0xa7, 0x06, 0x55, 0x23, 0x04, 0x8b, 0x2f, 0x83, 0x04, 0xea, + 0x83, 0x28, 0x2f, 0x7e, 0x1e, 0x0d, 0x82, 0xc8, 0xc1, 0x4f, 0x5a, 0x48, 0xd6, 0xb6, 0x42, 0x81, + 0x51, 0x27, 0xe9, 0x90, 0x14, 0xdf, 0x41, 0xf9, 0xe9, 0x75, 0xb3, 0x69, 0x38, 0xc4, 0xe2, 0x59, + 0x49, 0x9f, 0x48, 0x0e, 0x88, 0x36, 0x09, 0xff, 0x02, 0x2d, 0x6b, 0x4e, 0x83, 0x17, 0x93, 0xde, + 0x46, 0x71, 0xd8, 0xc4, 0x0f, 0xa4, 0x11, 0x0a, 0x0b, 0xe0, 0xc7, 0x51, 0xda, 0x7f, 0x80, 0xcb, + 0xdc, 0x54, 0x24, 0x0d, 0x4a, 0xc3, 0x52, 0xc1, 0xc7, 0x76, 0x7a, 0xd7, 0xb1, 0x7d, 0x07, 0xe5, + 0xd8, 0x89, 0x17, 0x78, 0x92, 0x0b, 0x51, 0x7f, 0xba, 0x36, 0x78, 0x12, 0xe8, 0xd9, 0x66, 0x16, + 0x2c, 0x4f, 0xc9, 0x2b, 0x9b, 0x31, 0x9b, 0x68, 0xa0, 0x7e, 0xf8, 0x0b, 0x5f, 0x46, 0x59, 0x90, + 0x62, 0x0a, 0xf6, 0xb1, 0x30, 0x4b, 0x47, 0xe4, 0x07, 0x78, 0xda, 0x4d, 0xd3, 0xb6, 0xe5, 0xd1, + 0xaa, 0xa1, 0xd5, 0xc3, 0x5c, 0x2e, 0x1c, 0x26, 0xc9, 0x85, 0xc3, 0xd4, 0x7f, 0x91, 0x4e, 0x08, + 0xfe, 0xf6, 0xe8, 0x0e, 0x93, 0x17, 0x11, 0x82, 0x87, 0xd6, 0x54, 0x9e, 0xfe, 0x13, 0x0d, 0x18, + 0x25, 0xc0, 0x08, 0xd4, 0x56, 0xda, 0x76, 0x84, 0xc4, 0xea, 0xaf, 0xa7, 0x62, 0x11, 0xc3, 0x8e, + 0x6b, 0x72, 0x6d, 0xf9, 0x5b, 0x8e, 0x77, 0xa2, 0x70, 0xf5, 0xeb, 0xe9, 0xa4, 0xf8, 0x69, 0xc7, + 0x53, 0xc5, 0xc3, 0x8c, 0x9f, 0xd9, 0x7d, 0x64, 0xfc, 0x7c, 0x0b, 0x8d, 0x45, 0xa2, 0x8a, 0xf1, + 0x84, 0x68, 0x97, 0x7b, 0x87, 0x27, 0xeb, 0xfe, 0x44, 0x5f, 0x22, 0x53, 0xff, 0x5f, 0xaa, 0x77, + 0x4c, 0xb9, 0x23, 0x57, 0x9d, 0x04, 0x01, 0x64, 0xfe, 0x6c, 0x04, 0xf0, 0x10, 0xb6, 0xc1, 0xc7, + 0x5b, 0x00, 0xef, 0x91, 0xc9, 0xe3, 0x9b, 0x2d, 0x80, 0x9f, 0x48, 0xed, 0x1a, 0x12, 0xf0, 0xa8, + 0x65, 0xa0, 0xfe, 0xa7, 0x54, 0x62, 0xe8, 0xbe, 0x43, 0xb5, 0xeb, 0x65, 0x94, 0x63, 0x6e, 0x35, + 0xbc, 0x55, 0x42, 0xb2, 0x03, 0x0a, 0xed, 0x96, 0x79, 0x9b, 0x61, 0xf1, 0x3c, 0x1a, 0x60, 0x6d, + 0x30, 0x78, 0x6f, 0x7c, 0xa0, 0x47, 0xfc, 0x40, 0xa3, 0xdb, 0xe4, 0xc8, 0xd1, 0xea, 0xaf, 0xa5, + 0x62, 0x91, 0x04, 0x8f, 0xf0, 0xdb, 0xc2, 0xa9, 0x3a, 0xb3, 0xf7, 0xa9, 0x5a, 0xfd, 0xbd, 0x74, + 0x72, 0x20, 0xc3, 0x23, 0xfc, 0x90, 0x87, 0x71, 0x9c, 0x76, 0xb0, 0x75, 0x6b, 0x19, 0x8d, 0xca, + 0xb2, 0xe0, 0xcb, 0xd6, 0xa5, 0xe4, 0x70, 0x8e, 0x5d, 0x5a, 0x11, 0xe1, 0xa1, 0xbe, 0x9b, 0x8a, + 0xc7, 0x60, 0x3c, 0xf2, 0xf9, 0xe9, 0x60, 0xda, 0x22, 0x7f, 0xca, 0x7b, 0x64, 0xad, 0x79, 0x18, + 0x9f, 0xf2, 0x1e, 0x59, 0x35, 0x0e, 0xf6, 0x29, 0x3f, 0x95, 0xee, 0x16, 0xc2, 0xf2, 0xc8, 0x3f, + 0xe8, 0x93, 0xa2, 0x90, 0x59, 0xcb, 0xf8, 0xa7, 0x3d, 0xde, 0x2d, 0x66, 0x64, 0x17, 0x9e, 0x31, + 0x3e, 0x07, 0x1b, 0xe3, 0x89, 0xc2, 0x7a, 0x8f, 0x28, 0xf2, 0xf1, 0x10, 0xd6, 0x7b, 0x64, 0xa8, + 0xbc, 0xf7, 0x84, 0xf5, 0xcb, 0xe9, 0xbd, 0xc6, 0x4d, 0x3d, 0x11, 0x5e, 0x4c, 0x78, 0x5f, 0x4c, + 0xc7, 0xe3, 0xf9, 0x1e, 0xb9, 0x98, 0x66, 0x51, 0x8e, 0x47, 0x16, 0xee, 0x2a, 0x1c, 0x86, 0xef, + 0x66, 0xd1, 0xf0, 0xef, 0x08, 0xd3, 0xb1, 0x67, 0xf7, 0x9e, 0x8e, 0x5d, 0xfd, 0xa3, 0x54, 0x24, + 0xf8, 0xed, 0x91, 0x1c, 0x21, 0x1c, 0x68, 0x49, 0xc2, 0xaf, 0xf8, 0x87, 0x99, 0xd9, 0x48, 0x5e, + 0xd1, 0xe0, 0x7b, 0xca, 0xc4, 0xd3, 0xcd, 0x66, 0xb4, 0x3c, 0x8f, 0x09, 0xf0, 0x95, 0x34, 0x1a, + 0x8f, 0x91, 0xe2, 0xcb, 0x52, 0x94, 0x1c, 0x38, 0x96, 0x8c, 0x38, 0x8f, 0xb3, 0x78, 0x39, 0xfb, + 0x38, 0x49, 0xbd, 0x8c, 0xb2, 0x65, 0x7d, 0x8b, 0x7d, 0x5b, 0x3f, 0x63, 0x69, 0xe8, 0x5b, 0xe2, + 0x89, 0x1b, 0xe0, 0xf1, 0x0a, 0x3a, 0xc3, 0xee, 0x43, 0x4c, 0xdb, 0x5a, 0x36, 0x5b, 0xa4, 0x62, + 0x2d, 0x98, 0xcd, 0xa6, 0xe9, 0xf2, 0x4b, 0xbd, 0x6b, 0x3b, 0xdb, 0xc5, 0x2b, 0x9e, 0xed, 0xe9, + 0xcd, 0x3a, 0xf1, 0xc9, 0xea, 0x9e, 0xd9, 0x22, 0x75, 0xd3, 0xaa, 0xb7, 0x80, 0x52, 0x60, 0x99, + 0xcc, 0x0a, 0x57, 0x58, 0x90, 0xca, 0x5a, 0x43, 0xb7, 0x2c, 0x62, 0x54, 0xac, 0xa9, 0x2d, 0x8f, + 0xb0, 0xcb, 0xc0, 0x0c, 0x3b, 0x12, 0x64, 0x6f, 0xc3, 0x19, 0x9a, 0x32, 0x5e, 0xa1, 0x04, 0x5a, + 0x42, 0x21, 0xf5, 0x57, 0xb2, 0x09, 0x71, 0x8f, 0x8f, 0x91, 0xfa, 0xf8, 0x3d, 0x9d, 0xdd, 0xa5, + 0xa7, 0xaf, 0xa3, 0x81, 0xbb, 0xc4, 0x81, 0xf3, 0x2d, 0x76, 0xc1, 0x00, 0xce, 0xec, 0xf7, 0x19, + 0x48, 0xbc, 0xa1, 0xe1, 0x54, 0xb8, 0x89, 0x26, 0x96, 0x69, 0x37, 0x25, 0x77, 0x66, 0xee, 0x00, + 0x9d, 0xd9, 0x83, 0x1f, 0x7e, 0x13, 0x9d, 0x03, 0x6c, 0x42, 0xb7, 0x0e, 0x40, 0x55, 0x10, 0x39, + 0x8a, 0x55, 0x95, 0xdc, 0xb9, 0xdd, 0xca, 0xe3, 0x4f, 0xa2, 0xe1, 0x60, 0x80, 0x98, 0xc4, 0xe5, + 0x37, 0x17, 0x3d, 0xc6, 0x19, 0x0b, 0xcb, 0x46, 0xc1, 0xe0, 0x42, 0x26, 0x87, 0xf6, 0x92, 0x78, + 0xa9, 0xff, 0x31, 0xd5, 0x2b, 0xfe, 0xf2, 0x91, 0xcf, 0xca, 0xaf, 0xa0, 0x01, 0x83, 0x7d, 0x14, + 0xd7, 0xa9, 0xde, 0x11, 0x9a, 0x19, 0xa9, 0xe6, 0x97, 0x51, 0x7f, 0x37, 0xd5, 0x33, 0xec, 0xf3, + 0x71, 0xff, 0xbc, 0x2f, 0x66, 0xba, 0x7c, 0x1e, 0x9f, 0x44, 0xaf, 0xa2, 0x82, 0x69, 0x79, 0x64, + 0x8d, 0x65, 0x74, 0xab, 0x87, 0xe1, 0xa7, 0xb4, 0x31, 0x01, 0x0e, 0xa3, 0xeb, 0x26, 0x3a, 0xeb, + 0x3b, 0x3e, 0x3a, 0xbe, 0x87, 0x98, 0x5b, 0xef, 0x38, 0x26, 0x1b, 0x97, 0xda, 0x69, 0x37, 0xe2, + 0x3e, 0xe6, 0xde, 0x71, 0x4c, 0x5a, 0x81, 0xee, 0xad, 0x13, 0x4b, 0xaf, 0x6f, 0xda, 0xce, 0x06, + 0xc4, 0xfe, 0x64, 0x83, 0x53, 0x1b, 0x63, 0xf0, 0x7b, 0x3e, 0x18, 0x3f, 0x89, 0x46, 0xd6, 0x9a, + 0x1d, 0x12, 0x44, 0x5b, 0x64, 0x77, 0x7d, 0xda, 0x30, 0x05, 0x06, 0x37, 0x24, 0x17, 0x11, 0x02, + 0x22, 0x0f, 0x82, 0x72, 0xc3, 0xc5, 0x9e, 0x36, 0x48, 0x21, 0xcb, 0xbc, 0xbb, 0x26, 0x98, 0x56, + 0x33, 0x21, 0xd5, 0x9b, 0xb6, 0xb5, 0x56, 0xf7, 0x88, 0xd3, 0x82, 0x86, 0x82, 0x33, 0x83, 0x76, + 0x16, 0x28, 0xe0, 0xea, 0xc4, 0x9d, 0xb7, 0xad, 0xb5, 0x65, 0xe2, 0xb4, 0x68, 0x53, 0xaf, 0x21, + 0xcc, 0x9b, 0xea, 0xc0, 0xa1, 0x07, 0xfb, 0x38, 0xf0, 0x66, 0xd0, 0xf8, 0x47, 0xb0, 0xd3, 0x10, + 0xf8, 0xb0, 0x22, 0x1a, 0x62, 0x21, 0xe7, 0x98, 0xd0, 0xc0, 0x85, 0x41, 0x43, 0x0c, 0x04, 0xf2, + 0x3a, 0x8b, 0xb8, 0x77, 0x05, 0xf3, 0xea, 0xd6, 0xf8, 0x2f, 0xf5, 0xf3, 0x99, 0xa4, 0x48, 0xd5, + 0x87, 0x52, 0xb4, 0x70, 0x5a, 0x4d, 0xef, 0x6b, 0x5a, 0x1d, 0xb3, 0x3a, 0xad, 0xba, 0xde, 0x6e, + 0xd7, 0x57, 0xcd, 0x26, 0x3c, 0xab, 0x82, 0x85, 0x4f, 0x1b, 0xb1, 0x3a, 0xad, 0x52, 0xbb, 0x3d, + 0xcb, 0x80, 0xf8, 0x29, 0x34, 0x4e, 0xe9, 0xa0, 0x93, 0x02, 0xca, 0x2c, 0x50, 0x52, 0x06, 0x10, + 0xb3, 0xd5, 0xa7, 0x3d, 0x8f, 0xf2, 0x9c, 0x27, 0x5b, 0xab, 0xfa, 0xb5, 0x01, 0xc6, 0xcc, 0xa5, + 0x3d, 0x17, 0xb0, 0x61, 0x93, 0x6b, 0xbf, 0x36, 0xe8, 0x97, 0x87, 0xc8, 0xc4, 0x56, 0xa7, 0xc5, + 0x22, 0x62, 0x0d, 0x00, 0x32, 0xf8, 0x8d, 0x2f, 0xa3, 0x51, 0xca, 0x25, 0x10, 0x18, 0x0b, 0xe6, + 0xda, 0xaf, 0x45, 0xa0, 0xf8, 0x06, 0x3a, 0x2d, 0x41, 0x98, 0x0d, 0xca, 0x9e, 0x09, 0xf4, 0x6b, + 0x89, 0x38, 0xf5, 0xdd, 0x4c, 0x3c, 0x10, 0xf7, 0x91, 0xac, 0x8d, 0x73, 0x08, 0xf1, 0x38, 0xfb, + 0xe1, 0x05, 0x4d, 0xe0, 0xb5, 0x1c, 0x62, 0xba, 0xf0, 0x10, 0xca, 0xe2, 0xab, 0x28, 0xcf, 0xbe, + 0xa8, 0x52, 0xe6, 0x6b, 0x26, 0xb8, 0x19, 0xb9, 0x6d, 0x73, 0x75, 0x15, 0x7c, 0x92, 0x02, 0x34, + 0xbe, 0x8c, 0x06, 0xca, 0x8b, 0xb5, 0x5a, 0x69, 0xd1, 0xbf, 0x6d, 0x84, 0x37, 0x0a, 0x86, 0xe5, + 0xd6, 0x5d, 0xdd, 0x72, 0x35, 0x1f, 0x89, 0x9f, 0x44, 0xb9, 0x4a, 0x15, 0xc8, 0xd8, 0xcb, 0xbb, + 0xa1, 0x9d, 0xed, 0xe2, 0x80, 0xd9, 0x66, 0x54, 0x1c, 0x05, 0xf5, 0xde, 0xad, 0x94, 0x85, 0x2b, + 0x77, 0x56, 0xef, 0x7d, 0xd3, 0x80, 0xab, 0x4b, 0x2d, 0x40, 0xe3, 0xe7, 0xd0, 0x70, 0x8d, 0x38, + 0xa6, 0xde, 0x5c, 0xec, 0xc0, 0x76, 0x83, 0xb9, 0x19, 0x8d, 0xef, 0x6c, 0x17, 0x47, 0x5c, 0x80, + 0xd7, 0x2d, 0x40, 0x68, 0x12, 0x19, 0xbe, 0x80, 0xb2, 0x73, 0xa6, 0xe5, 0xbb, 0xc1, 0x83, 0x9f, + 0xf4, 0xba, 0x69, 0x79, 0x1a, 0x40, 0xd5, 0xef, 0x4d, 0x27, 0x87, 0x42, 0x3f, 0x82, 0xb1, 0x75, + 0xc0, 0xdb, 0xc2, 0x88, 0x12, 0x64, 0x0f, 0xae, 0x04, 0xea, 0xf7, 0xa7, 0x77, 0x89, 0xaa, 0xfe, + 0x48, 0x4a, 0xe5, 0x4b, 0xe9, 0xde, 0x81, 0xed, 0x1f, 0x49, 0xa1, 0x7c, 0x25, 0x23, 0x86, 0x99, + 0x7f, 0x74, 0xbd, 0x2f, 0x6e, 0x4a, 0x3e, 0x97, 0x7b, 0xed, 0xbf, 0xe7, 0x78, 0x38, 0x01, 0xa3, + 0xe3, 0xf8, 0xee, 0x49, 0xc1, 0x73, 0x66, 0x00, 0x8a, 0x8e, 0x46, 0x01, 0x25, 0xae, 0xa0, 0x6c, + 0xc9, 0x59, 0x63, 0x6b, 0xdd, 0x6e, 0x2f, 0x2c, 0x74, 0x67, 0xcd, 0x4d, 0x7e, 0x61, 0x41, 0x59, + 0x3c, 0xb5, 0xc0, 0x62, 0x87, 0xde, 0x36, 0x2d, 0x03, 0x9f, 0x47, 0x67, 0xee, 0xd4, 0x66, 0xb4, + 0xfa, 0xed, 0xca, 0x62, 0xb9, 0x7e, 0x67, 0xb1, 0x56, 0x9d, 0x99, 0xae, 0xcc, 0x56, 0x66, 0xca, + 0x85, 0x3e, 0x7c, 0x0a, 0x8d, 0x85, 0xa8, 0xb9, 0x3b, 0x0b, 0xa5, 0xc5, 0x42, 0x0a, 0x8f, 0xa3, + 0x91, 0x10, 0x38, 0xb5, 0xb4, 0x5c, 0x48, 0x3f, 0xf5, 0x21, 0x34, 0x04, 0xc6, 0x51, 0x89, 0xad, + 0x26, 0xc3, 0x28, 0xbf, 0x34, 0x55, 0x9b, 0xd1, 0xee, 0x02, 0x13, 0x84, 0x72, 0xe5, 0x99, 0x45, + 0xca, 0x30, 0xf5, 0xd4, 0xff, 0x49, 0x21, 0x54, 0x9b, 0x5d, 0xae, 0x72, 0xc2, 0x21, 0x34, 0x50, + 0x59, 0xbc, 0x5b, 0x9a, 0xaf, 0x50, 0xba, 0x3c, 0xca, 0x2e, 0x55, 0x67, 0x68, 0x0d, 0x83, 0xa8, + 0x7f, 0x7a, 0x7e, 0xa9, 0x36, 0x53, 0x48, 0x53, 0xa0, 0x36, 0x53, 0x2a, 0x17, 0x32, 0x14, 0x78, + 0x4f, 0xab, 0x2c, 0xcf, 0x14, 0xb2, 0xf4, 0xcf, 0xf9, 0xda, 0x72, 0x69, 0xb9, 0xd0, 0x4f, 0xff, + 0x9c, 0x85, 0x3f, 0x73, 0x94, 0x59, 0x6d, 0x66, 0x19, 0x7e, 0x0c, 0xd0, 0x26, 0xcc, 0xfa, 0xbf, + 0xf2, 0x14, 0x45, 0x59, 0x97, 0x2b, 0x5a, 0x61, 0x90, 0xfe, 0xa0, 0x2c, 0xe9, 0x0f, 0x44, 0x1b, + 0xa7, 0xcd, 0x2c, 0x2c, 0xdd, 0x9d, 0x29, 0x0c, 0x51, 0x5e, 0x0b, 0xb7, 0x29, 0x78, 0x98, 0xfe, + 0xa9, 0x2d, 0xd0, 0x3f, 0x47, 0x28, 0x27, 0x6d, 0xa6, 0x34, 0x5f, 0x2d, 0x2d, 0xcf, 0x15, 0x46, + 0x69, 0x7b, 0x80, 0xe7, 0x18, 0x2b, 0xb9, 0x58, 0x5a, 0x98, 0x29, 0x14, 0x38, 0x4d, 0x79, 0xbe, + 0xb2, 0x78, 0xbb, 0x30, 0x0e, 0x0d, 0x79, 0x73, 0x01, 0x7e, 0x60, 0x5a, 0x00, 0xfe, 0x3a, 0xf5, + 0xd4, 0xb7, 0xa0, 0xdc, 0x52, 0x0d, 0x96, 0xb2, 0x73, 0xe8, 0xd4, 0x52, 0xad, 0xbe, 0xfc, 0x66, + 0x75, 0x26, 0x22, 0xef, 0x71, 0x34, 0xe2, 0x23, 0xe6, 0x2b, 0x8b, 0x77, 0x3e, 0xc1, 0xa4, 0xed, + 0x83, 0x16, 0x4a, 0xd3, 0x4b, 0xb5, 0x42, 0x9a, 0xf6, 0x8a, 0x0f, 0xba, 0x57, 0x59, 0x2c, 0x2f, + 0xdd, 0xab, 0x15, 0x32, 0x4f, 0xdd, 0xf7, 0x33, 0xa4, 0x2d, 0x39, 0xe6, 0x9a, 0x69, 0xe1, 0x8b, + 0xe8, 0x7c, 0x79, 0xe6, 0x6e, 0x65, 0x7a, 0xa6, 0xbe, 0xa4, 0x55, 0x6e, 0x55, 0x16, 0x23, 0x35, + 0x9d, 0x41, 0xe3, 0x32, 0xba, 0x54, 0xad, 0x14, 0x52, 0xf8, 0x2c, 0xc2, 0x32, 0xf8, 0xf5, 0xd2, + 0xc2, 0x6c, 0x21, 0x8d, 0x15, 0x74, 0x5a, 0x86, 0x57, 0x16, 0x97, 0xef, 0x2c, 0xce, 0x14, 0x32, + 0x4f, 0xfd, 0x9d, 0x14, 0x3a, 0x93, 0xf8, 0x3a, 0x17, 0xab, 0xe8, 0xd2, 0xcc, 0x7c, 0xa9, 0xb6, + 0x5c, 0x99, 0xae, 0xcd, 0x94, 0xb4, 0xe9, 0xb9, 0xfa, 0x74, 0x69, 0x79, 0xe6, 0xd6, 0x92, 0xf6, + 0x66, 0xfd, 0xd6, 0xcc, 0xe2, 0x8c, 0x56, 0x9a, 0x2f, 0xf4, 0xe1, 0x27, 0x51, 0xb1, 0x0b, 0x4d, + 0x6d, 0x66, 0xfa, 0x8e, 0x56, 0x59, 0x7e, 0xb3, 0x90, 0xc2, 0x4f, 0xa0, 0x8b, 0x5d, 0x89, 0xe8, + 0xef, 0x42, 0x1a, 0x5f, 0x42, 0x13, 0xdd, 0x48, 0xde, 0x98, 0x2f, 0x64, 0x9e, 0xfa, 0xe1, 0x14, + 0xc2, 0xf1, 0xe7, 0x95, 0xf8, 0x71, 0x74, 0x81, 0xea, 0x45, 0xbd, 0x7b, 0x03, 0x9f, 0x40, 0x17, + 0x13, 0x29, 0x84, 0xe6, 0x15, 0xd1, 0x63, 0x5d, 0x48, 0x78, 0xe3, 0x2e, 0x20, 0x25, 0x99, 0x80, + 0x36, 0x6d, 0xaa, 0xfc, 0xee, 0x7f, 0xbe, 0xd4, 0xf7, 0xee, 0xef, 0x5f, 0x4a, 0xfd, 0xe6, 0xef, + 0x5f, 0x4a, 0xfd, 0xde, 0xef, 0x5f, 0x4a, 0x7d, 0xf2, 0xc6, 0x7e, 0x5e, 0x9f, 0xb2, 0xf9, 0x66, + 0x25, 0x07, 0xb3, 0xc0, 0xb3, 0xff, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x4e, 0xee, 0xdf, 0x37, 0x77, + 0x3f, 0x01, 0x00, } func (m *Metadata) Marshal() (dAtA []byte, err error) { @@ -26497,6 +26570,29 @@ func (m *OneOf_DatabaseUserDeactivate) MarshalToSizedBuffer(dAtA []byte) (int, e } return len(dAtA) - i, nil } +func (m *OneOf_SpannerRPC) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *OneOf_SpannerRPC) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.SpannerRPC != nil { + { + size, err := m.SpannerRPC.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x9 + i-- + dAtA[i] = 0xf2 + } + return len(dAtA) - i, nil +} func (m *StreamStatus) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -26521,12 +26617,12 @@ func (m *StreamStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } - n559, err559 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastUploadTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.LastUploadTime):]) - if err559 != nil { - return 0, err559 + n560, err560 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastUploadTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.LastUploadTime):]) + if err560 != nil { + return 0, err560 } - i -= n559 - i = encodeVarintEvents(dAtA, i, uint64(n559)) + i -= n560 + i = encodeVarintEvents(dAtA, i, uint64(n560)) i-- dAtA[i] = 0x1a if m.LastEventIndex != 0 { @@ -26676,12 +26772,12 @@ func (m *Identity) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0xc2 } } - n563, err563 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.PreviousIdentityExpires, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.PreviousIdentityExpires):]) - if err563 != nil { - return 0, err563 + n564, err564 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.PreviousIdentityExpires, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.PreviousIdentityExpires):]) + if err564 != nil { + return 0, err564 } - i -= n563 - i = encodeVarintEvents(dAtA, i, uint64(n563)) + i -= n564 + i = encodeVarintEvents(dAtA, i, uint64(n564)) i-- dAtA[i] = 0x1 i-- @@ -26829,12 +26925,12 @@ func (m *Identity) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x4a } - n567, err567 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expires, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expires):]) - if err567 != nil { - return 0, err567 + n568, err568 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expires, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expires):]) + if err568 != nil { + return 0, err568 } - i -= n567 - i = encodeVarintEvents(dAtA, i, uint64(n567)) + i -= n568 + i = encodeVarintEvents(dAtA, i, uint64(n568)) i-- dAtA[i] = 0x42 if len(m.KubernetesUsers) > 0 { @@ -31714,6 +31810,102 @@ func (m *SessionRecordingConfigUpdate) MarshalToSizedBuffer(dAtA []byte) (int, e return len(dAtA) - i, nil } +func (m *SpannerRPC) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SpannerRPC) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SpannerRPC) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if m.Args != nil { + { + size, err := m.Args.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + if len(m.Procedure) > 0 { + i -= len(m.Procedure) + copy(dAtA[i:], m.Procedure) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Procedure))) + i-- + dAtA[i] = 0x32 + } + { + size, err := m.Status.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + { + size, err := m.DatabaseMetadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size, err := m.SessionMetadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.UserMetadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func encodeVarintEvents(dAtA []byte, offset int, v uint64) int { offset -= sovEvents(v) base := offset @@ -37024,6 +37216,18 @@ func (m *OneOf_DatabaseUserDeactivate) Size() (n int) { } return n } +func (m *OneOf_SpannerRPC) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SpannerRPC != nil { + l = m.SpannerRPC.Size() + n += 2 + l + sovEvents(uint64(l)) + } + return n +} func (m *StreamStatus) Size() (n int) { if m == nil { return 0 @@ -38944,6 +39148,36 @@ func (m *SessionRecordingConfigUpdate) Size() (n int) { return n } +func (m *SpannerRPC) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Metadata.Size() + n += 1 + l + sovEvents(uint64(l)) + l = m.UserMetadata.Size() + n += 1 + l + sovEvents(uint64(l)) + l = m.SessionMetadata.Size() + n += 1 + l + sovEvents(uint64(l)) + l = m.DatabaseMetadata.Size() + n += 1 + l + sovEvents(uint64(l)) + l = m.Status.Size() + n += 1 + l + sovEvents(uint64(l)) + l = len(m.Procedure) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + if m.Args != nil { + l = m.Args.Size() + n += 1 + l + sovEvents(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func sovEvents(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -72782,6 +73016,41 @@ func (m *OneOf) Unmarshal(dAtA []byte) error { } m.Event = &OneOf_DatabaseUserDeactivate{v} iNdEx = postIndex + case 158: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SpannerRPC", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &SpannerRPC{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Event = &OneOf_SpannerRPC{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipEvents(dAtA[iNdEx:]) @@ -88279,6 +88548,290 @@ func (m *SessionRecordingConfigUpdate) Unmarshal(dAtA []byte) error { } return nil } +func (m *SpannerRPC) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SpannerRPC: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SpannerRPC: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UserMetadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.UserMetadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SessionMetadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SessionMetadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DatabaseMetadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.DatabaseMetadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Status.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Procedure", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Procedure = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Args", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Args == nil { + m.Args = &Struct{} + } + if err := m.Args.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipEvents(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/api/types/events/oneof.go b/api/types/events/oneof.go index e0b2bb9f08b3a..f136a852da46a 100644 --- a/api/types/events/oneof.go +++ b/api/types/events/oneof.go @@ -655,6 +655,10 @@ func ToOneOf(in AuditEvent) (*OneOf, error) { out.Event = &OneOf_DatabaseUserDeactivate{ DatabaseUserDeactivate: e, } + case *SpannerRPC: + out.Event = &OneOf_SpannerRPC{ + SpannerRPC: e, + } default: log.Errorf("Attempted to convert dynamic event of unknown type \"%v\" into protobuf event.", in.GetType()) diff --git a/api/utils/gcp/endpoint.go b/api/utils/gcp/endpoint.go index a178d0f90b23e..8ef26b8c298ae 100644 --- a/api/utils/gcp/endpoint.go +++ b/api/utils/gcp/endpoint.go @@ -21,9 +21,17 @@ import ( const ( // gcpEndpointSuffix is hostname suffix used to determine if hostname is a GCP endpoint gcpEndpointSuffix = ".googleapis.com" + + // SpannerEndpoint is the endpoint that all spanner RPCs should go to. + SpannerEndpoint = "spanner" + gcpEndpointSuffix + ":443" ) // IsGCPEndpoint returns true if hostname is a GCP endpoint func IsGCPEndpoint(hostname string) bool { return strings.HasSuffix(hostname, gcpEndpointSuffix) } + +// IsSpannerEndpoint returns true if the input URI is the Spanner API endpoint. +func IsSpannerEndpoint(uri string) bool { + return uri == SpannerEndpoint +} diff --git a/go.mod b/go.mod index 88c24978c5d07..2b236857fd3a8 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( cloud.google.com/go/iam v1.1.7 cloud.google.com/go/kms v1.15.8 cloud.google.com/go/resourcemanager v1.9.7 + cloud.google.com/go/spanner v1.60.0 cloud.google.com/go/storage v1.39.1 connectrpc.com/connect v1.15.0 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0 @@ -278,9 +279,11 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/boombuler/barcode v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect github.com/cloudflare/cfssl v1.6.4 // indirect + github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/log v0.1.0 // indirect @@ -307,6 +310,8 @@ require ( github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/elastic/elastic-transport-go/v8 v8.3.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/envoyproxy/go-control-plane v0.12.0 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fatih/camelcase v1.0.0 // indirect diff --git a/go.sum b/go.sum index 5eb57a5ca58a0..568a11356cb8b 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ cloud.google.com/go/pubsub v1.37.0 h1:0uEEfaB1VIJzabPpwpZf44zWAKAme3zwKKxHk7vJQx cloud.google.com/go/pubsub v1.37.0/go.mod h1:YQOQr1uiUM092EXwKs56OPT650nwnawc+8/IjoUeGzQ= cloud.google.com/go/resourcemanager v1.9.7 h1:SdvD0PaPX60+yeKoSe16mawFpM0EPuiPPihTIVlhRsY= cloud.google.com/go/resourcemanager v1.9.7/go.mod h1:cQH6lJwESufxEu6KepsoNAsjrUtYYNXRwxm4QFE5g8A= +cloud.google.com/go/spanner v1.60.0 h1:O9kf49dfaDRzPpKJNChHUJ+Bao02WPedZb8ZPyi02lI= +cloud.google.com/go/spanner v1.60.0/go.mod h1:D2bOAeT/dC6zsZhXRIxbdYa5nQEYU3wYM/1KN3eg7Fs= cloud.google.com/go/storage v1.39.1 h1:MvraqHKhogCOTXTlct/9C3K3+Uy2jBmFYb3/Sp6dVtY= cloud.google.com/go/storage v1.39.1/go.mod h1:xK6xZmxZmo+fyP7+DEF6FhNc24/JAe95OLyOHCXFH1o= connectrpc.com/connect v1.15.0 h1:lFdeCbZrVVDydAqwr4xGV2y+ULn+0Z73s5JBj2LikWo= @@ -369,6 +371,8 @@ github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4r github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -399,6 +403,8 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= @@ -519,7 +525,11 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= diff --git a/lib/client/db/dbcmd/dbcmd.go b/lib/client/db/dbcmd/dbcmd.go index ed52858c4d721..3528ce29b269f 100644 --- a/lib/client/db/dbcmd/dbcmd.go +++ b/lib/client/db/dbcmd/dbcmd.go @@ -33,6 +33,7 @@ import ( "go.mongodb.org/mongo-driver/x/mongo/driver/connstring" "github.com/gravitational/teleport/api/constants" + "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/client" "github.com/gravitational/teleport/lib/client/db" "github.com/gravitational/teleport/lib/client/db/mysql" @@ -78,6 +79,8 @@ const ( awsBin = "aws" // oracleBin is the Oracle CLI program name. oracleBin = "sql" + // spannerBin is a Google Spanner interactive CLI program name. + spannerBin = "spanner-cli" ) // Execer is an abstraction of Go's exec module, as this one doesn't specify any interfaces. @@ -206,6 +209,8 @@ func (c *CLICommandBuilder) GetConnectCommand() (*exec.Cmd, error) { case defaults.ProtocolClickHouse: return c.getClickhouseNativeCommand() + case defaults.ProtocolSpanner: + return c.getSpannerCommand() } return nil, trace.BadParameter("unsupported database protocol: %v", c.db) @@ -668,15 +673,23 @@ func (c *CLICommandBuilder) getOpenSearchCLICommand() (*exec.Cmd, error) { return exec.Command(openSearchCLIBin, args...), nil } -func (c *CLICommandBuilder) getDynamoDBCommand() (*exec.Cmd, error) { - // we can't guess at what the user wants to do, so this command is for print purposes only, - // and it only works with a local proxy tunnel. - if !c.options.printFormat || !c.options.noTLS || c.options.localProxyHost == "" || c.options.localProxyPort == 0 { +func (c *CLICommandBuilder) checkLocalProxyTunnelOnly(requirePrint bool) error { + if (requirePrint && !c.options.printFormat) || !c.options.noTLS || c.options.localProxyHost == "" || c.options.localProxyPort == 0 { svc := "" if c.db != nil && c.db.ServiceName != "" { svc = c.db.ServiceName } - return nil, trace.BadParameter("DynamoDB requires a local proxy tunnel. Use `tsh proxy db --tunnel %v`", svc) + protocol := defaults.ReadableDatabaseProtocol(c.db.Protocol) + return trace.BadParameter("%s requires a local proxy tunnel. Use `tsh proxy db --tunnel %v`", protocol, svc) + } + return nil +} + +func (c *CLICommandBuilder) getDynamoDBCommand() (*exec.Cmd, error) { + // we can't guess at what the user wants to do, so this command is for print + // purposes only, and it only works with a local proxy tunnel. + if err := c.checkLocalProxyTunnelOnly(true); err != nil { + return nil, trace.Wrap(err) } args := []string{ "--endpoint", fmt.Sprintf("http://%v:%v/", c.options.localProxyHost, c.options.localProxyPort), @@ -686,6 +699,52 @@ func (c *CLICommandBuilder) getDynamoDBCommand() (*exec.Cmd, error) { return exec.Command(awsBin, args...), nil } +func (c *CLICommandBuilder) getSpannerCommand() (*exec.Cmd, error) { + if err := c.checkLocalProxyTunnelOnly(false); err != nil { + return nil, trace.Wrap(err) + } + var ( + project, + instance, + database string + ) + if c.options.printFormat { + // default placeholders for a print command if not all info is available + project, instance, database = "", "", "" + } + + if c.options.gcp.ProjectID != "" { + project = c.options.gcp.ProjectID + } + if c.options.gcp.InstanceID != "" { + instance = c.options.gcp.InstanceID + } + if c.db.Database != "" { + database = c.db.Database + } + + protocol := defaults.ReadableDatabaseProtocol(c.db.Protocol) + switch { + case project == "": + return nil, trace.BadParameter("missing GCP project ID for %s command (this is a bug)", protocol) + case instance == "": + return nil, trace.BadParameter("missing GCP instance ID for %s command (this is a bug)", protocol) + case database == "": + return nil, trace.BadParameter("missing database name for %s command (this is a bug)", protocol) + } + + args := []string{ + "-p", project, + "-i", instance, + "-d", database, + } + cmd := exec.Command(spannerBin, args...) + cmd.Env = append(cmd.Env, + fmt.Sprintf("SPANNER_EMULATOR_HOST=%s:%d", c.host, c.port), + ) + return cmd, nil +} + type jdbcOracleThinConnection struct { host string port int @@ -814,6 +873,7 @@ type connectionCommandOpts struct { log *logrus.Entry exe Execer password string + gcp types.GCPCloudSQL } // ConnectCommandFunc is a type for functions returned by the "With*" functions in this package. @@ -903,6 +963,13 @@ func WithExecer(exe Execer) ConnectCommandFunc { } } +// WithGCP adds GCP metadata for the database command to access. +func WithGCP(gcp types.GCPCloudSQL) ConnectCommandFunc { + return func(opts *connectionCommandOpts) { + opts.gcp = gcp + } +} + const ( // envVarMongoServerSelectionTimeoutMS is the environment variable that // controls the server selection timeout used for MongoDB clients. diff --git a/lib/client/db/dbcmd/dbcmd_test.go b/lib/client/db/dbcmd/dbcmd_test.go index 73e9e830ecefb..2a26458602c94 100644 --- a/lib/client/db/dbcmd/dbcmd_test.go +++ b/lib/client/db/dbcmd/dbcmd_test.go @@ -26,6 +26,7 @@ import ( "github.com/gravitational/trace" "github.com/stretchr/testify/require" + "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/client" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/fixtures" @@ -630,6 +631,102 @@ func TestCLICommandBuilderGetConnectCommand(t *testing.T) { cmd: []string{"sql", "-L", "'jdbc:oracle:thin:@tcps://localhost:12345/oracle01?TNS_ADMIN=/tmp/keys/example.com/bob-db/mysql-wallet'"}, wantErr: false, }, + { + name: "Spanner for exec is ok", + dbProtocol: defaults.ProtocolSpanner, + opts: []ConnectCommandFunc{ + WithLocalProxy("localhost", 12345, ""), + WithNoTLS(), + WithGCP(types.GCPCloudSQL{ProjectID: "foo-proj", InstanceID: "bar-instance"}), + }, + execer: &fakeExec{}, + databaseName: "googlesql-db", + cmd: []string{"spanner-cli", "-p", "foo-proj", "-i", "bar-instance", "-d", "googlesql-db"}, + wantErr: false, + }, + { + name: "Spanner with print format is ok", + dbProtocol: defaults.ProtocolSpanner, + opts: []ConnectCommandFunc{ + WithPrintFormat(), + WithLocalProxy("localhost", 12345, ""), + WithNoTLS(), + WithGCP(types.GCPCloudSQL{ProjectID: "foo-proj", InstanceID: "bar-instance"}), + }, + execer: &fakeExec{}, + databaseName: "googlesql-db", + cmd: []string{"spanner-cli", "-p", "foo-proj", "-i", "bar-instance", "-d", "googlesql-db"}, + wantErr: false, + }, + { + name: "Spanner with print format and placeholders is ok", + dbProtocol: defaults.ProtocolSpanner, + opts: []ConnectCommandFunc{ + WithPrintFormat(), + WithLocalProxy("localhost", 12345, ""), + WithNoTLS(), + WithGCP(types.GCPCloudSQL{}), + }, + execer: &fakeExec{}, + databaseName: "", + cmd: []string{"spanner-cli", "-p", "", "-i", "", "-d", ""}, + wantErr: false, + }, + { + name: "Spanner for exec without GCP project is an error", + dbProtocol: defaults.ProtocolSpanner, + opts: []ConnectCommandFunc{ + WithLocalProxy("localhost", 12345, ""), + WithNoTLS(), + WithGCP(types.GCPCloudSQL{InstanceID: "bar-instance"}), + }, + execer: &fakeExec{}, + databaseName: "googlesql-db", + wantErr: true, + }, + { + name: "Spanner for exec without GCP instance is an error", + dbProtocol: defaults.ProtocolSpanner, + opts: []ConnectCommandFunc{ + WithLocalProxy("localhost", 12345, ""), + WithNoTLS(), + WithGCP(types.GCPCloudSQL{ProjectID: "foo-proj"}), + }, + execer: &fakeExec{}, + databaseName: "googlesql-db", + wantErr: true, + }, + { + name: "Spanner for exec without database name is an error", + dbProtocol: defaults.ProtocolSpanner, + opts: []ConnectCommandFunc{ + WithLocalProxy("localhost", 12345, ""), + WithNoTLS(), + WithGCP(types.GCPCloudSQL{ProjectID: "foo-proj"}), + }, + execer: &fakeExec{}, + databaseName: "googlesql-db", + wantErr: true, + }, + { + name: "Spanner without a local proxy is an error", + dbProtocol: defaults.ProtocolSpanner, + opts: []ConnectCommandFunc{ + WithLocalProxy("", 0, ""), + WithNoTLS(), + WithGCP(types.GCPCloudSQL{ProjectID: "foo-proj", InstanceID: "bar-instance"}), + }, + execer: &fakeExec{}, + databaseName: "googlesql-db", + wantErr: true, + }, + { + name: "Spanner with TLS local proxy is an error", + dbProtocol: defaults.ProtocolSpanner, + opts: []ConnectCommandFunc{WithPrintFormat(), WithLocalProxy("localhost", 12345, "")}, + execer: &fakeExec{}, + wantErr: true, + }, } for _, tt := range tests { diff --git a/lib/defaults/defaults.go b/lib/defaults/defaults.go index d1fb08f33b425..7ec2b9b654eaa 100644 --- a/lib/defaults/defaults.go +++ b/lib/defaults/defaults.go @@ -478,6 +478,8 @@ const ( ProtocolClickHouse = "clickhouse" // ProtocolClickHouseHTTP is the ClickHouse database HTTP protocol. ProtocolClickHouseHTTP = "clickhouse-http" + // ProtocolSpanner is the GCP Spanner database protocol. + ProtocolSpanner = "spanner" ) // DatabaseProtocols is a list of all supported database protocols. @@ -496,6 +498,7 @@ var DatabaseProtocols = []string{ ProtocolDynamoDB, ProtocolClickHouse, ProtocolClickHouseHTTP, + ProtocolSpanner, } // ReadableDatabaseProtocol returns a more human-readable string of the @@ -530,6 +533,8 @@ func ReadableDatabaseProtocol(p string) string { return "Clickhouse" case ProtocolClickHouseHTTP: return "Clickhouse (HTTP)" + case ProtocolSpanner: + return "GCloud Spanner" default: // Unknown protocol. Return original string. return p diff --git a/lib/events/api.go b/lib/events/api.go index 7dd0db719f6c5..cb036475da4eb 100644 --- a/lib/events/api.go +++ b/lib/events/api.go @@ -532,6 +532,10 @@ const ( // DatabaseSessionCassandraRegisterEvent is emitted when a Cassandra client sends the register packet. DatabaseSessionCassandraRegisterEvent = "db.session.cassandra.register" + // DatabaseSessionSpannerRPCEvent is emitted when a Spanner client + // calls a Spanner RPC. + DatabaseSessionSpannerRPCEvent = "db.session.spanner.rpc" + // SessionRejectedReasonMaxConnections indicates that a session.rejected event // corresponds to enforcement of the max_connections control. SessionRejectedReasonMaxConnections = "max_connections limit reached" diff --git a/lib/events/codes.go b/lib/events/codes.go index 07bc53f98c203..3f4798134a798 100644 --- a/lib/events/codes.go +++ b/lib/events/codes.go @@ -230,6 +230,12 @@ const ( // This is indicates that the database agent http transport failed to round trip the request. DynamoDBRequestFailureCode = "TDY01E" + // SpannerRPCCode is the db.session.spanner.rpc event code. + SpannerRPCCode = "TSPN001I" + // SpannerRPCDeniedCode is the warning event code for a Spanner client RPC + // that is denied. + SpannerRPCDeniedCode = "TSPN001W" + // DatabaseCreateCode is the db.create event code. DatabaseCreateCode = "TDB03I" // DatabaseUpdateCode is the db.update event code. diff --git a/lib/events/dynamic.go b/lib/events/dynamic.go index 3ec76d21b588c..6a19de476770f 100644 --- a/lib/events/dynamic.go +++ b/lib/events/dynamic.go @@ -369,7 +369,8 @@ func FromEventFields(fields EventFields) (events.AuditEvent, error) { e = &events.ClusterNetworkingConfigUpdate{} case SessionRecordingConfigUpdateEvent: e = &events.SessionRecordingConfigUpdate{} - + case DatabaseSessionSpannerRPCEvent: + e = &events.SpannerRPC{} case UnknownEvent: e = &events.Unknown{} diff --git a/lib/events/eventstest/channel.go b/lib/events/eventstest/channel.go index 3f90c871be104..cafd98b71ceee 100644 --- a/lib/events/eventstest/channel.go +++ b/lib/events/eventstest/channel.go @@ -20,6 +20,7 @@ package eventstest import ( "context" + "time" "github.com/sirupsen/logrus" @@ -44,11 +45,19 @@ func NewChannelEmitter(capacity int) *ChannelEmitter { func (e *ChannelEmitter) EmitAuditEvent(ctx context.Context, event apievents.AuditEvent) error { e.log.Infof("EmitAuditEvent(%v)", event) - select { - case <-ctx.Done(): - return ctx.Err() - case e.events <- event: - return nil + start := time.Now() + for { + select { + case <-ctx.Done(): + return ctx.Err() + case e.events <- event: + return nil + case <-time.After(5 * time.Second): + e.log.WithFields(logrus.Fields{ + "event": event, + "elapsed": time.Since(start), + }).Info("EmitAuditEvent has been blocked sending to a full ChannelEmitter for a long time") + } } } @@ -88,11 +97,19 @@ func (*ChannelRecorder) Write(b []byte) (int, error) { func (e *ChannelRecorder) RecordEvent(ctx context.Context, event apievents.PreparedSessionEvent) error { e.log.Infof("RecordEvent(%v)", event.GetAuditEvent()) - select { - case <-ctx.Done(): - return ctx.Err() - case e.events <- event.GetAuditEvent(): - return nil + start := time.Now() + for { + select { + case <-ctx.Done(): + return ctx.Err() + case e.events <- event.GetAuditEvent(): + return nil + case <-time.After(5 * time.Second): + e.log.WithFields(logrus.Fields{ + "event": event.GetAuditEvent(), + "elapsed": time.Since(start), + }).Info("RecordEvent has been blocked sending to a full ChannelRecorder for a long time") + } } } diff --git a/lib/service/service.go b/lib/service/service.go index a098f723229a1..dee5421d8c120 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -4804,7 +4804,9 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { alpncommon.ProtocolRedisDB, alpncommon.ProtocolSnowflake, alpncommon.ProtocolSQLServer, - alpncommon.ProtocolCassandra), + alpncommon.ProtocolCassandra, + alpncommon.ProtocolSpanner, + ), }) } diff --git a/lib/service/service_test.go b/lib/service/service_test.go index a0d6ec94475e3..9db2ff1aeb66c 100644 --- a/lib/service/service_test.go +++ b/lib/service/service_test.go @@ -805,6 +805,7 @@ func TestSetupProxyTLSConfig(t *testing.T) { "teleport-opensearch-ping", "teleport-dynamodb-ping", "teleport-clickhouse-ping", + "teleport-spanner-ping", "teleport-proxy-ssh", "teleport-reversetunnel", "teleport-auth@", @@ -824,6 +825,7 @@ func TestSetupProxyTLSConfig(t *testing.T) { "teleport-opensearch", "teleport-dynamodb", "teleport-clickhouse", + "teleport-spanner", }, }, { @@ -843,6 +845,7 @@ func TestSetupProxyTLSConfig(t *testing.T) { "teleport-opensearch-ping", "teleport-dynamodb-ping", "teleport-clickhouse-ping", + "teleport-spanner-ping", // Ensure http/1.1 has precedence over http2. "http/1.1", "h2", @@ -865,6 +868,7 @@ func TestSetupProxyTLSConfig(t *testing.T) { "teleport-opensearch", "teleport-dynamodb", "teleport-clickhouse", + "teleport-spanner", }, }, } diff --git a/lib/services/database.go b/lib/services/database.go index eb2e5361bfb33..e3331a3eef476 100644 --- a/lib/services/database.go +++ b/lib/services/database.go @@ -34,6 +34,7 @@ import ( "github.com/gravitational/teleport/api/types" azureutils "github.com/gravitational/teleport/api/utils/azure" + gcputils "github.com/gravitational/teleport/api/utils/gcp" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/srv/db/common/enterprise" "github.com/gravitational/teleport/lib/srv/db/redis/connection" @@ -157,6 +158,11 @@ func ValidateDatabase(db types.Database) error { if err := ValidateSQLServerURI(db.GetURI()); err != nil { return trace.BadParameter("invalid SQL Server address: %v", err) } + } else if db.GetProtocol() == defaults.ProtocolSpanner { + if !gcputils.IsSpannerEndpoint(db.GetURI()) { + return trace.BadParameter("GCP Spanner database %q address should be %q", + db.GetName(), gcputils.SpannerEndpoint) + } } else if needsURIValidation(db) { if _, _, err := net.SplitHostPort(db.GetURI()); err != nil { return trace.BadParameter("invalid database %q address %q: %v", db.GetName(), db.GetURI(), err) diff --git a/lib/services/database_test.go b/lib/services/database_test.go index c2de0475eb5ef..3820c30d827ea 100644 --- a/lib/services/database_test.go +++ b/lib/services/database_test.go @@ -252,6 +252,53 @@ func TestValidateDatabase(t *testing.T) { }, expectError: false, }, + { + inputName: "valid-spanner-without-uri", + inputSpec: types.DatabaseSpecV3{ + Protocol: defaults.ProtocolSpanner, + GCP: types.GCPCloudSQL{ + ProjectID: "project-id", + InstanceID: "instance-id", + }, + }, + expectError: false, + }, + { + inputName: "valid-spanner-with-uri", + inputSpec: types.DatabaseSpecV3{ + Protocol: defaults.ProtocolSpanner, + URI: "spanner.googleapis.com:443", + GCP: types.GCPCloudSQL{ + ProjectID: "project-id", + InstanceID: "instance-id", + }, + }, + expectError: false, + }, + { + inputName: "invalid-spanner-uri-host", + inputSpec: types.DatabaseSpecV3{ + Protocol: defaults.ProtocolSpanner, + URI: "foo.googleapis.com:443", + GCP: types.GCPCloudSQL{ + ProjectID: "project-id", + InstanceID: "instance-id", + }, + }, + expectError: true, + }, + { + inputName: "invalid-spanner-uri-missing-port", + inputSpec: types.DatabaseSpecV3{ + Protocol: defaults.ProtocolSpanner, + URI: "spanner.googleapis.com", + GCP: types.GCPCloudSQL{ + ProjectID: "project-id", + InstanceID: "instance-id", + }, + }, + expectError: true, + }, { inputName: "invalid-mssql-without-ad", inputSpec: types.DatabaseSpecV3{ diff --git a/lib/srv/alpnproxy/common/protocols.go b/lib/srv/alpnproxy/common/protocols.go index bf0042fa28d89..d4cbbcfa4c190 100644 --- a/lib/srv/alpnproxy/common/protocols.go +++ b/lib/srv/alpnproxy/common/protocols.go @@ -68,6 +68,9 @@ const ( // ProtocolClickhouse is TLS ALPN protocol value used to indicate Clickhouse Protocol. ProtocolClickhouse Protocol = "teleport-clickhouse" + // ProtocolSpanner is TLS ALPN protocol value used to indicate Google Spanner (gRPC) Protocol. + ProtocolSpanner Protocol = "teleport-spanner" + // ProtocolProxySSH is TLS ALPN protocol value used to indicate Proxy SSH protocol. ProtocolProxySSH Protocol = "teleport-proxy-ssh" @@ -174,6 +177,8 @@ func ToALPNProtocol(dbProtocol string) (Protocol, error) { return ProtocolDynamoDB, nil case defaults.ProtocolClickHouse, defaults.ProtocolClickHouseHTTP: return ProtocolClickhouse, nil + case defaults.ProtocolSpanner: + return ProtocolSpanner, nil default: return "", trace.NotImplemented("%q protocol is not supported", dbProtocol) } @@ -196,6 +201,7 @@ func IsDBTLSProtocol(protocol Protocol) bool { ProtocolOpenSearch, ProtocolDynamoDB, ProtocolClickhouse, + ProtocolSpanner, } return slices.ContainsFunc(dbTLSProtocols, func(dbTLSProtocol Protocol) bool { @@ -217,6 +223,7 @@ var DatabaseProtocols = []Protocol{ ProtocolOpenSearch, ProtocolDynamoDB, ProtocolClickhouse, + ProtocolSpanner, } // ProtocolsWithPingSupport is the list of protocols that Ping connection is diff --git a/lib/srv/db/access_test.go b/lib/srv/db/access_test.go index b1ecbd1e4ce7d..303af62eab0d3 100644 --- a/lib/srv/db/access_test.go +++ b/lib/srv/db/access_test.go @@ -32,6 +32,7 @@ import ( "testing" "time" + gspanner "cloud.google.com/go/spanner" "github.com/ClickHouse/ch-go" cqlclient "github.com/datastax/go-cassandra-native-protocol/client" elastic "github.com/elastic/go-elasticsearch/v8" @@ -87,6 +88,7 @@ import ( redisprotocol "github.com/gravitational/teleport/lib/srv/db/redis/protocol" "github.com/gravitational/teleport/lib/srv/db/secrets" "github.com/gravitational/teleport/lib/srv/db/snowflake" + "github.com/gravitational/teleport/lib/srv/db/spanner" "github.com/gravitational/teleport/lib/srv/db/sqlserver" "github.com/gravitational/teleport/lib/tlsca" "github.com/gravitational/teleport/lib/utils" @@ -1460,6 +1462,8 @@ type testContext struct { dynamodb map[string]testDynamoDB // clickHouse is a collection of ClickHouse databases the test uses. clickHouse map[string]testClickHouse + // spanner is a collection of Spanner databases the test uses. + spanner map[string]testSpannerDB // clock to override clock in tests. clock clockwork.FakeClock @@ -1549,6 +1553,14 @@ type testDynamoDB struct { resource types.Database } +// testSpannerDB represents a single proxied Spanner database. +type testSpannerDB struct { + // db is the test Spanner database server. + db *spanner.TestServer + // resource is the resource representing this Spanner database. + resource types.Database +} + // startProxy starts all proxy services required to handle connections. func (c *testContext) startProxy() { // Start multiplexer. @@ -2088,8 +2100,48 @@ func (c *testContext) dynamodbClient(ctx context.Context, teleportUser, dbServic return db, proxy, nil } +func (c *testContext) spannerClient(ctx context.Context, teleportUser, dbService, dbUser, dbName string) (*gspanner.Client, *alpnproxy.LocalProxy, error) { + route := tlsca.RouteToDatabase{ + ServiceName: dbService, + Protocol: defaults.ProtocolSpanner, + Username: dbUser, + Database: dbName, + } + + proxy, err := c.startLocalALPNProxy(ctx, c.webListener.Addr().String(), teleportUser, route) + if err != nil { + return nil, nil, trace.Wrap(err) + } + + db, err := spanner.MakeTestClient(ctx, common.TestClientConfig{ + AuthClient: c.authClient, + AuthServer: c.authServer, + Address: proxy.GetAddr(), + Cluster: c.clusterName, + Username: teleportUser, + RouteToDatabase: route, + }) + if err != nil { + return nil, nil, trace.Wrap(err) + } + + return db, proxy, nil +} + type roleOptFn func(types.Role) +func withDeniedDatabaseUsers(users ...string) roleOptFn { + return func(role types.Role) { + role.SetDatabaseUsers(types.Deny, users) + } +} + +func withDeniedDatabaseNames(names ...string) roleOptFn { + return func(role types.Role) { + role.SetDatabaseNames(types.Deny, names) + } +} + func withAllowedDBLabels(labels types.Labels) roleOptFn { return func(role types.Role) { role.SetDatabaseLabels(types.Allow, labels) @@ -2178,6 +2230,7 @@ func setupTestContext(ctx context.Context, t testing.TB, withDatabases ...withDa cassandra: make(map[string]testCassandra), dynamodb: make(map[string]testDynamoDB), clickHouse: make(map[string]testClickHouse), + spanner: make(map[string]testSpannerDB), clock: clockwork.NewFakeClockAt(time.Now()), } t.Cleanup(func() { testCtx.Close() }) @@ -2276,6 +2329,9 @@ func setupTestContext(ctx context.Context, t testing.TB, withDatabases ...withDa require.NoError(t, err) // Create test audit events emitter. + // NOTE(gavin): this emitter is just a buffered channel and it will block if + // a test does not consume the events, which can make your test fail + // mysteriously with a timeout. testCtx.emitter = eventstest.NewChannelEmitter(100) connMonitor, err := srv.NewConnectionMonitor(srv.ConnectionMonitorConfig{ diff --git a/lib/srv/db/audit_test.go b/lib/srv/db/audit_test.go index 65dc6802b7f38..513714a4f41d4 100644 --- a/lib/srv/db/audit_test.go +++ b/lib/srv/db/audit_test.go @@ -400,7 +400,7 @@ func waitForAnyEvent(t *testing.T, testCtx *testContext) events.AuditEvent { case event := <-testCtx.emitter.C(): return event case <-time.After(time.Second): - t.Fatalf("didn't receive any event after 1 second") + require.FailNow(t, "timed out waiting for an audit event", "didn't receive any event after 1 second") } return nil } @@ -422,7 +422,16 @@ func waitForEvent(t *testing.T, testCtx *testContext, code string) events.AuditE } return event case <-time.After(time.Second): - t.Fatalf("didn't receive %v event after 1 second", code) + require.FailNow(t, "timed out waiting for an audit event", "didn't receive %v event after 1 second", code) } } } + +// requireSpannerRPCEvent waits for a spanner RPC audit event or fails the test. +func requireSpannerRPCEvent(t *testing.T, testCtx *testContext) *events.SpannerRPC { + t.Helper() + evt := waitForEvent(t, testCtx, libevents.SpannerRPCCode) + rpcEvt, ok := evt.(*events.SpannerRPC) + require.True(t, ok) + return rpcEvt +} diff --git a/lib/srv/db/auth_test.go b/lib/srv/db/auth_test.go index 3227fcb313dc0..f3d827aa47df2 100644 --- a/lib/srv/db/auth_test.go +++ b/lib/srv/db/auth_test.go @@ -21,6 +21,7 @@ package db import ( "context" "testing" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/elasticache" @@ -28,6 +29,7 @@ import ( "github.com/gravitational/trace" "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" + "golang.org/x/oauth2" "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/types" @@ -62,6 +64,8 @@ func TestAuthTokens(t *testing.T) { withElastiCacheRedis("redis-elasticache-incorrect-token", "qwe123", "7.0.0"), withMemoryDBRedis("redis-memorydb-correct-token", memorydbToken, "7.0"), withMemoryDBRedis("redis-memorydb-incorrect-token", "qwe123", "7.0"), + withSpanner("spanner-correct-token", cloudSpannerAuthToken), + withSpanner("spanner-incorrect-token", "xyz123"), } databases := make([]types.Database, 0, len(withDBs)) for _, withDB := range withDBs { @@ -186,6 +190,17 @@ func TestAuthTokens(t *testing.T) { // Make sure we print a user-friendly IAM auth error. err: "Make sure that IAM auth is enabled", }, + { + desc: "correct Spanner auth token", + service: "spanner-correct-token", + protocol: defaults.ProtocolSpanner, + }, + { + desc: "incorrect Spanner auth token", + service: "spanner-incorrect-token", + protocol: defaults.ProtocolSpanner, + err: "invalid RPC auth token", + }, } for _, test := range tests { @@ -218,6 +233,23 @@ func TestAuthTokens(t *testing.T) { require.NoError(t, err) require.NoError(t, conn.Close()) } + case defaults.ProtocolSpanner: + clt, localProxy, err := testCtx.spannerClient(ctx, "alice", test.service, "admin", "somedb") + // Teleport doesn't actually try to fetch a token until an RPC + // is received, so it shouldn't fail after connecting. + require.NoError(t, err) + t.Cleanup(func() { + // Disconnect. + clt.Close() + _ = localProxy.Close() + }) + _, err = pingSpanner(ctx, clt, 123) + if test.err != "" { + require.Error(t, err) + require.Contains(t, err.Error(), test.err) + } else { + require.NoError(t, err) + } default: t.Fatalf("unrecognized database protocol in test: %q", test.protocol) } @@ -256,6 +288,8 @@ const ( cloudSQLAuthToken = "cloudsql-auth-token" // cloudSQLPassword is a mock Cloud SQL user password. cloudSQLPassword = "cloudsql-password" + // cloudSpannerAuthToken is a mock Cloud Spanner IAM auth token. + cloudSpannerAuthToken = "cloud-spanner-auth-token" // azureAccessToken is a mock Azure access token. azureAccessToken = "azure-access-token" // azureRedisToken is a mock Azure Redis token. @@ -272,6 +306,21 @@ const ( atlasAuthSessionToken = "atlas-session-token" ) +type fakeTokenSource struct { + logrus.FieldLogger + + token string + exp time.Time +} + +func (f *fakeTokenSource) Token() (*oauth2.Token, error) { + f.Infof("Generating Cloud Spanner auth token source") + return &oauth2.Token{ + Expiry: f.exp, + AccessToken: f.token, + }, nil +} + // GetRDSAuthToken generates RDS/Aurora auth token. func (a *testAuth) GetRDSAuthToken(ctx context.Context, sessionCtx *common.Session) (string, error) { a.Infof("Generating RDS auth token for %v.", sessionCtx) @@ -302,6 +351,14 @@ func (a *testAuth) GetCloudSQLAuthToken(ctx context.Context, sessionCtx *common. return cloudSQLAuthToken, nil } +// GetSpannerTokenSource returns an oauth token source for GCP Spanner. +func (a *testAuth) GetSpannerTokenSource(ctx context.Context, sessionCtx *common.Session) (oauth2.TokenSource, error) { + return &fakeTokenSource{ + token: cloudSpannerAuthToken, + FieldLogger: a.WithField("session", sessionCtx), + }, nil +} + // GetCloudSQLPassword generates Cloud SQL user password. func (a *testAuth) GetCloudSQLPassword(ctx context.Context, sessionCtx *common.Session) (string, error) { a.Infof("Generating Cloud SQL user password %v.", sessionCtx) diff --git a/lib/srv/db/ca.go b/lib/srv/db/ca.go index 7aeab023e4bdb..be7f081dc1f1b 100644 --- a/lib/srv/db/ca.go +++ b/lib/srv/db/ca.go @@ -109,6 +109,8 @@ func (s *Server) shouldInitCACertLocked(database types.Database) bool { types.DatabaseTypeDynamoDB, types.DatabaseTypeMongoAtlas, types.DatabaseTypeCloudSQL, + // GCP Spanner is intentionally omitted, because the GCP Spanner endpoint + // is issued by a public CA. types.DatabaseTypeAzure: return true default: diff --git a/lib/srv/db/common/auth.go b/lib/srv/db/common/auth.go index f5b8f2b38144e..b1381d97e819f 100644 --- a/lib/srv/db/common/auth.go +++ b/lib/srv/db/common/auth.go @@ -30,6 +30,7 @@ import ( "strings" "time" + gcpcredentials "cloud.google.com/go/iam/credentials/apiv1" gcpcredentialspb "cloud.google.com/go/iam/credentials/apiv1/credentialspb" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" @@ -44,6 +45,7 @@ import ( "github.com/gravitational/trace" "github.com/jonboulle/clockwork" "github.com/sirupsen/logrus" + "golang.org/x/oauth2" sqladmin "google.golang.org/api/sqladmin/v1beta4" "github.com/gravitational/teleport" @@ -81,6 +83,8 @@ type Auth interface { GetMemoryDBToken(ctx context.Context, sessionCtx *Session) (string, error) // GetCloudSQLAuthToken generates Cloud SQL auth token. GetCloudSQLAuthToken(ctx context.Context, sessionCtx *Session) (string, error) + // GetSpannerTokenSource returns an oauth token source for GCP Spanner. + GetSpannerTokenSource(ctx context.Context, sessionCtx *Session) (oauth2.TokenSource, error) // GetCloudSQLPassword generates password for a Cloud SQL database user. GetCloudSQLPassword(ctx context.Context, sessionCtx *Session) (string, error) // GetAzureAccessToken generates Azure database access token. @@ -371,36 +375,85 @@ Make sure that IAM role %q has permissions to generate credentials. Here is a sa // GetCloudSQLAuthToken returns authorization token that will be used as a // password when connecting to Cloud SQL databases. func (a *dbAuth) GetCloudSQLAuthToken(ctx context.Context, sessionCtx *Session) (string, error) { - gcpIAM, err := a.cfg.Clients.GetGCPIAMClient(ctx) + // https://developers.google.com/identity/protocols/oauth2/scopes#sqladmin + scopes := []string{ + "https://www.googleapis.com/auth/sqlservice.admin", + } + ts, err := a.getCloudTokenSource(ctx, sessionCtx, scopes) + if err != nil { + return "", trace.Wrap(err) + } + tok, err := ts.Token() if err != nil { return "", trace.Wrap(err) } - a.cfg.Log.Debugf("Generating GCP auth token for %s.", sessionCtx) + return tok.AccessToken, nil +} + +// GetSpannerTokenSource returns an oauth token source for GCP Spanner. +func (a *dbAuth) GetSpannerTokenSource(ctx context.Context, sessionCtx *Session) (oauth2.TokenSource, error) { + // https://developers.google.com/identity/protocols/oauth2/scopes#spanner + scopes := []string{ + "https://www.googleapis.com/auth/spanner.data", + } + ts, err := a.getCloudTokenSource(ctx, sessionCtx, scopes) + if err != nil { + return nil, trace.Wrap(err) + } + // refreshes the credentials as needed. + return oauth2.ReuseTokenSource(nil, ts), nil +} +func (a *dbAuth) getCloudTokenSource(ctx context.Context, sessionCtx *Session, scopes []string) (*cloudTokenSource, error) { + gcpIAM, err := a.cfg.Clients.GetGCPIAMClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } serviceAccountName := sessionCtx.DatabaseUser if !strings.HasSuffix(serviceAccountName, ".gserviceaccount.com") { serviceAccountName = serviceAccountName + ".gserviceaccount.com" } - resp, err := gcpIAM.GenerateAccessToken(ctx, + return &cloudTokenSource{ + ctx: ctx, + client: gcpIAM, + log: a.cfg.Log.WithField("session", sessionCtx.String()), + serviceAccount: serviceAccountName, + scopes: scopes, + }, nil +} + +// cloudTokenSource implements [oauth2.TokenSource] and logs each time it's +// used to fetch a token. +type cloudTokenSource struct { + ctx context.Context + client *gcpcredentials.IamCredentialsClient + log logrus.FieldLogger + serviceAccount string + scopes []string +} + +// Token returns a token or an error. +// Token must be safe for concurrent use by multiple goroutines. +// The returned Token must not be modified. +func (l *cloudTokenSource) Token() (*oauth2.Token, error) { + l.log.Debug("Generating GCP auth token") + resp, err := l.client.GenerateAccessToken(l.ctx, &gcpcredentialspb.GenerateAccessTokenRequest{ // From GenerateAccessToken docs: // // The resource name of the service account for which the credentials // are requested, in the following format: // projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID} - Name: fmt.Sprintf("projects/-/serviceAccounts/%v", serviceAccountName), + Name: fmt.Sprintf("projects/-/serviceAccounts/%v", l.serviceAccount), // From GenerateAccessToken docs: // // Code to identify the scopes to be included in the OAuth 2.0 access // token: // https://developers.google.com/identity/protocols/oauth2/scopes - // https://developers.google.com/identity/protocols/oauth2/scopes#sqladmin - Scope: []string{ - "https://www.googleapis.com/auth/sqlservice.admin", - }, + Scope: l.scopes, }) if err != nil { - return "", trace.AccessDenied(`Could not generate GCP IAM auth token: + return nil, trace.AccessDenied(`Could not generate GCP IAM auth token: %v @@ -408,7 +461,10 @@ Make sure Teleport db service has "Service Account Token Creator" GCP IAM role, or "iam.serviceAccounts.getAccessToken" IAM permission. `, err) } - return resp.AccessToken, nil + return &oauth2.Token{ + AccessToken: resp.AccessToken, + Expiry: resp.ExpireTime.AsTime(), + }, nil } // GetCloudSQLPassword updates the specified database user's password to a @@ -767,6 +823,9 @@ func shouldUseSystemCertPool(sessionCtx *Session) bool { case types.DatabaseTypeOpenSearch: // OpenSearch is commonly hosted on AWS and uses Amazon Root CAs. return true + case types.DatabaseTypeSpanner: + // Spanner is hosted on GCP. + return true } return false } diff --git a/lib/srv/db/common/auth_test.go b/lib/srv/db/common/auth_test.go index dc5b69f547343..51d7b1a88956f 100644 --- a/lib/srv/db/common/auth_test.go +++ b/lib/srv/db/common/auth_test.go @@ -204,6 +204,12 @@ func TestAuthGetTLSConfig(t *testing.T) { expectInsecureSkipVerify: true, expectVerifyConnection: true, }, + { + name: "GCP Spanner", + sessionDatabase: newSpannerDatabase(t, ""), + expectServerName: "spanner.googleapis.com", + expectRootCAs: systemCertPool, + }, { name: "Azure SQL Server", sessionDatabase: newAzureSQLDatabase(t, "resource-id"), @@ -873,6 +879,25 @@ func newAzureSQLDatabase(t *testing.T, resourceID string) types.Database { return database } +func newSpannerDatabase(t *testing.T, uri string, specOpts ...databaseSpecOpt) types.Database { + spec := types.DatabaseSpecV3{ + Protocol: defaults.ProtocolSpanner, + URI: uri, + GCP: types.GCPCloudSQL{ + ProjectID: "project-id", + InstanceID: "instance-id", + }, + } + for _, opt := range specOpts { + opt(&spec) + } + database, err := types.NewDatabaseV3(types.Metadata{ + Name: "test-database", + }, spec) + require.NoError(t, err) + return database +} + // identityResourceID generates full resource ID of the Azure user identity. func identityResourceID(t *testing.T, identityName string) string { t.Helper() diff --git a/lib/srv/db/common/reporting.go b/lib/srv/db/common/reporting.go index 7de478683afcb..22263ec1dcce6 100644 --- a/lib/srv/db/common/reporting.go +++ b/lib/srv/db/common/reporting.go @@ -238,3 +238,10 @@ func GetMessagesFromClientMetric(db types.Database) prometheus.Counter { func GetMessagesFromServerMetric(db types.Database) prometheus.Counter { return messagesFromServer.WithLabelValues(teleport.ComponentDatabase, db.GetProtocol(), db.GetType()) } + +// GetEngineErrorsMetric increments the synthetic errors sent by an engine to +// a client. +func GetEngineErrorsMetric(db types.Database) prometheus.Counter { + l := getLabels(teleport.ComponentDatabase, db) + return engineErrors.With(l) +} diff --git a/lib/srv/db/common/session.go b/lib/srv/db/common/session.go index 4a37b48f3e1ba..b70b0f4c9b135 100644 --- a/lib/srv/db/common/session.go +++ b/lib/srv/db/common/session.go @@ -88,6 +88,14 @@ func (c *Session) WithUser(user string) *Session { return © } +// WithDatabase returns a shallow copy of the session with overridden +// database name. +func (c *Session) WithDatabase(defaultDatabase string) *Session { + copy := *c + copy.DatabaseName = defaultDatabase + return © +} + // WithUserAndDatabase returns a shallow copy of the session with overridden // database user and overridden database name. func (c *Session) WithUserAndDatabase(user string, defaultDatabase string) *Session { diff --git a/lib/srv/db/server.go b/lib/srv/db/server.go index 3dfc3f9d6a6f0..f415b6bcb4936 100644 --- a/lib/srv/db/server.go +++ b/lib/srv/db/server.go @@ -60,6 +60,7 @@ import ( "github.com/gravitational/teleport/lib/srv/db/postgres" "github.com/gravitational/teleport/lib/srv/db/redis" "github.com/gravitational/teleport/lib/srv/db/snowflake" + "github.com/gravitational/teleport/lib/srv/db/spanner" "github.com/gravitational/teleport/lib/srv/db/sqlserver" discoverycommon "github.com/gravitational/teleport/lib/srv/discovery/common" "github.com/gravitational/teleport/lib/utils" @@ -78,6 +79,7 @@ func init() { common.RegisterEngine(dynamodb.NewEngine, defaults.ProtocolDynamoDB) common.RegisterEngine(clickhouse.NewEngine, defaults.ProtocolClickHouse) common.RegisterEngine(clickhouse.NewEngine, defaults.ProtocolClickHouseHTTP) + common.RegisterEngine(spanner.NewEngine, defaults.ProtocolSpanner) } // Config is the configuration for a database proxy server. diff --git a/lib/srv/db/spanner/doc.go b/lib/srv/db/spanner/doc.go new file mode 100644 index 0000000000000..3aa5d0ff4ba22 --- /dev/null +++ b/lib/srv/db/spanner/doc.go @@ -0,0 +1,92 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +// Package spanner implements GCP Spanner protocol support for database access. +// +// It has the following components: +// +// - Engine. Runs inside Teleport database service, accepts connections coming +// from proxy over reverse tunnel and proxies them to GCP Spanner databases. +// +// # Connection flow +// +// New connections arrive as a plain TLS TCP connection, which is handed +// off to the engine's internal grpc server to negotiate grpc inside the TLS +// tunnel. +// The engine avoids returning any error prior to setting up its internal grpc +// server and handing the connection over to it. +// This includes the initial access check, which is instead done on the first +// RPC received. +// In doing so, errors from access checks or otherwise can be sent to the +// client, which helps to avoid an ungraceful connection close and improves +// the user experience when something goes wrong - they can see a descriptive +// message instead of an unhelpful "deadline exceeded" and their client won't +// hopelessly retry on access denied errors or hang until a timeout. +// +// If any RPC is denied by Teleport RBAC, the engine's internal grpc server will +// shutdown. +// This is technically unnecessary, but improves the user experience because +// their client will see the connection closing and wont continue to send RPCs +// over that connection. +// From the client perspective, access denied errors are coming from Spanner +// itself. This would normally just mean a particular RPC is not allowed by +// GCloud's RBAC, but Teleport RBAC is not so fine-grained. As such, it's better +// to just shutdown than let the client software think that there's any hope +// of making any further RPCs. +// +// # Spanner Protocols +// +// Spanner has a REST API and a RPC API. +// The engine only proxies the [Spanner RPC] API. +// +// In Spanner, clients must first request a [Spanner Session], then execute +// RPCs using that session's ID. +// The complete session ID is generated when the session is created and returned +// to the client in the response. +// +// # RPCs +// +// Every RPC will include an ID. +// That ID is usually a session ID, but the session suffix is not there for +// RPCs that request a new session. +// The ID looks like this: +// "projects//instances//databases/[/sessions/]". +// Teleport will check that the ID's project and instance match the Teleport +// db object's GCP metadata and then check that the user is authorized to +// access . +// Whether or not is valid is up to GCloud to check. +// A ID is not a secret, by the way. +// +// # Auditing +// +// When a client connects, the db.session.start event is emitted after the +// first RPC is processed. By virtue of Spanner's session creation flow, this +// will always be either the CreateSessionRequest or BatchCreateSessionsRequest +// RPC for any properly written client. All RPCs are blocked until +// db.session.start is emitted, by design. +// If access is denied for the first RPC, then all RPCs will return the same +// access denied error and there will be no db.session.end nor RPC audit events. +// Otherwise, each RPC including the first RPC will emit a +// db.session.spanner.rpc event. +// That event will also indicate whether Teleport attempted to relay the RPC +// to GCloud Spanner - it will not attempt to do so if Teleport RBAC denies +// access or if there's an issue with marshaling the RPC into an audit event. +// +// [Spanner RPC]: https://cloud.google.com/spanner/docs/reference/rpc +// [Spanner Session]: https://cloud.google.com/spanner/docs/sessions +package spanner diff --git a/lib/srv/db/spanner/engine.go b/lib/srv/db/spanner/engine.go new file mode 100644 index 0000000000000..264f91d5dfd45 --- /dev/null +++ b/lib/srv/db/spanner/engine.go @@ -0,0 +1,176 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package spanner + +import ( + "context" + "errors" + "io" + "net" + "sync" + + "cloud.google.com/go/spanner/apiv1/spannerpb" + "github.com/gravitational/trace" + "github.com/prometheus/client_golang/prometheus" + gtransport "google.golang.org/api/transport/grpc" + "google.golang.org/grpc" + + "github.com/gravitational/teleport/api/utils/grpc/interceptors" + "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/srv/db/common" + "github.com/gravitational/teleport/lib/utils" +) + +// NewEngine creates a new Spanner engine. +func NewEngine(ec common.EngineConfig) common.Engine { + return &Engine{ + EngineConfig: ec, + } +} + +// Engine implements common.Engine. +type Engine struct { + // EngineConfig is the common database engine configuration. + common.EngineConfig + // clientConn is a client connection. + clientConn net.Conn + // clientConnContext is the connection context passed into HandleConnection. + // It's used to control the upstream connection (and credentials refresher) + // lifetime, and canceled when the engine exits. + clientConnContext context.Context + // cancelContext is used to cancel clientConnContext. + cancelContext context.CancelCauseFunc + // sessionCtx is current session context. + sessionCtx *common.Session + // instanceID is used for authz and is of the form + // projects//instances//, + // where the project ID and instance ID come from the Teleport database's + // GCP metadata. + // Every RPC that specifies a database name must be prefixed by this or the + // RPC will be denied. + instanceID string + + // mu guards access to gcloudClient + mu sync.Mutex + // gcloudConn is an upstream client to Google cloud API used to forward RPCs + // to the real Spanner API. + gcloudClient gtransport.ConnPool + + // sessionStarted is true after the session start event has been emitted. + sessionStarted bool + // sessionStartErr is the error (or nil) from the first RPC access check + // that starts the session. + sessionStartErr error + // startSessionOnce is used to start the session only once. + startSessionOnce sync.Once + + // connSetupObserverFn observes connection setup after the first authorized + // RPC triggers a dial to GCP. + connSetupObserverFn func() + // engineErrors tracks synthetic errors sent by the engine to a client. + // Since all access/auditing errors within the gRPC server must be handled + // within the gRPC server, the usual engine.SendError mechanism is not + // enough to track all errors sent to the client. + engineErrors prometheus.Counter + + // UnimplementedSpannerServer is embedded for forward interface compat. + spannerpb.UnimplementedSpannerServer +} + +// InitializeConnection initializes the database connection. +func (e *Engine) InitializeConnection(clientConn net.Conn, sessionCtx *common.Session) error { + e.clientConn = clientConn + gcp := sessionCtx.Database.GetGCP() + e.instanceID = "projects/" + gcp.ProjectID + "/instances/" + gcp.InstanceID + "/" + e.sessionCtx = sessionCtx + return nil +} + +func (e *Engine) SendError(err error) { + if err == nil || utils.IsOKNetworkError(err) { + return + } + // the grpc server handles sending all errors, if an error is sent outside + // of that, just log it here. + e.Log.WithError(err).Debug("GCP Spanner connection error") +} + +// HandleConnection processes the connection from the proxy coming over reverse +// tunnel. +func (e *Engine) HandleConnection(ctx context.Context, _ *common.Session) error { + e.connSetupObserverFn = common.GetConnectionSetupTimeObserver(e.sessionCtx.Database) + e.engineErrors = common.GetEngineErrorsMetric(e.sessionCtx.Database) + + ctx, cancel := context.WithCancelCause(ctx) + defer cancel(nil) + e.clientConnContext = ctx + e.cancelContext = cancel + + // stand up a gRPC grpcServer to handle the client connection. + grpcServer := grpc.NewServer( + grpc.ChainUnaryInterceptor(e.unaryServerInterceptors()...), + grpc.ChainStreamInterceptor(e.streamServerInterceptors()...), + grpc.MaxConcurrentStreams(defaults.GRPCMaxConcurrentStreams), + grpc.StatsHandler(&messageStatsHandler{ + messagesReceived: common.GetMessagesFromClientMetric(e.sessionCtx.Database), + }), + ) + // register server services to proxy RPCs. + spannerpb.RegisterSpannerServer(grpcServer, e) + + // this doesn't block, because the listener returns when Accept is called + // for a second time. + err := grpcServer.Serve(newSingleUseListener(e.clientConn)) + if err != nil && !errors.Is(err, io.EOF) { + return trace.Wrap(err) + } + select { + case <-ctx.Done(): + case <-e.Context.Done(): + } + + // this will cause the server to reject all new RPCs and block until all + // outstanding handlers have returned. + grpcServer.GracefulStop() + if e.gcloudClient != nil { + e.gcloudClient.Close() + } + + // emit a session end event if the session was started successfully. + if e.sessionStarted && e.sessionStartErr == nil { + e.Audit.OnSessionEnd(e.Context, e.sessionCtx) + } + return trace.Wrap(context.Cause(ctx)) +} + +func (e *Engine) unaryServerInterceptors() []grpc.UnaryServerInterceptor { + // intercept and log some info, then convert errors to gRPC codes. + return []grpc.UnaryServerInterceptor{ + interceptors.GRPCServerUnaryErrorInterceptor, + unaryServerLoggingInterceptor(e.Log), + } +} + +func (e *Engine) streamServerInterceptors() []grpc.StreamServerInterceptor { + // intercept and log some info, then convert errors to gRPC codes. + return []grpc.StreamServerInterceptor{ + interceptors.GRPCServerStreamErrorInterceptor, + streamServerLoggingInterceptor(e.Log), + } +} diff --git a/lib/srv/db/spanner/events.go b/lib/srv/db/spanner/events.go new file mode 100644 index 0000000000000..9b74cbf99084e --- /dev/null +++ b/lib/srv/db/spanner/events.go @@ -0,0 +1,73 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package spanner + +import ( + "context" + + "github.com/gravitational/trace" + + "github.com/gravitational/teleport/api/types/events" + libevents "github.com/gravitational/teleport/lib/events" + "github.com/gravitational/teleport/lib/srv/db/common" +) + +// rpcInfo contains information about a remote procedure call. +type rpcInfo struct { + // database is the name of the Spanner database within the instance for + // which the RPC was called. This can be different for each RPC, overriding + // the session database name as long as Teleport RBAC allows it. + database string + // procedure is the name of the remote procedure. + procedure string + // args is the RPC including all arguments. + args *events.Struct + // err contains an error if the RPC was rejected by Teleport. + err error +} + +func auditRPC(ctx context.Context, audit common.Audit, sessionCtx *common.Session, r rpcInfo) { + audit.EmitEvent(ctx, makeRPCEvent(sessionCtx, r)) +} + +func makeRPCEvent(sessionCtx *common.Session, r rpcInfo) *events.SpannerRPC { + sessionCtx = sessionCtx.WithDatabase(r.database) + event := &events.SpannerRPC{ + Metadata: common.MakeEventMetadata(sessionCtx, + libevents.DatabaseSessionSpannerRPCEvent, + libevents.SpannerRPCCode), + UserMetadata: common.MakeUserMetadata(sessionCtx), + SessionMetadata: common.MakeSessionMetadata(sessionCtx), + DatabaseMetadata: common.MakeDatabaseMetadata(sessionCtx), + Status: events.Status{ + Success: true, + }, + Procedure: r.procedure, + Args: r.args, + } + if r.err != nil { + event.Metadata.Code = libevents.SpannerRPCDeniedCode + event.Status = events.Status{ + Success: false, + Error: trace.Unwrap(r.err).Error(), + UserMessage: r.err.Error(), + } + } + return event +} diff --git a/lib/srv/db/spanner/grpcserver.go b/lib/srv/db/spanner/grpcserver.go new file mode 100644 index 0000000000000..3af1e7d773170 --- /dev/null +++ b/lib/srv/db/spanner/grpcserver.go @@ -0,0 +1,517 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package spanner + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "strings" + + spannerapi "cloud.google.com/go/spanner/apiv1" + "cloud.google.com/go/spanner/apiv1/spannerpb" + "github.com/gravitational/trace" + "github.com/prometheus/client_golang/prometheus" + "google.golang.org/api/option" + gtransport "google.golang.org/api/transport/grpc" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/stats" + "google.golang.org/protobuf/types/known/emptypb" + + "github.com/gravitational/teleport/api/types/events" + "github.com/gravitational/teleport/lib/srv/db/common" + "github.com/gravitational/teleport/lib/srv/db/common/role" +) + +type upstream[T any] interface { + Recv() (T, error) + grpc.ClientStream +} + +type downstream[T any] interface { + Send(T) error + grpc.ServerStream +} + +func proxyServerStream[T any](ctx context.Context, up upstream[T], down downstream[T]) error { + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + res, err := up.Recv() + if err != nil { + if errors.Is(err, io.EOF) { + // EOF is expected and signals end of the server stream. + return nil + } + return trace.Wrap(err) + } + + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + if err := down.Send(res); err != nil { + return trace.Wrap(err) + } + } +} + +func (e *Engine) CreateSession(ctx context.Context, req *spannerpb.CreateSessionRequest) (*spannerpb.Session, error) { + if err := e.authorizeRPCRequest(ctx, req.GetDatabase(), "CreateSession", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.CreateSession(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) BatchCreateSessions(ctx context.Context, req *spannerpb.BatchCreateSessionsRequest) (*spannerpb.BatchCreateSessionsResponse, error) { + if err := e.authorizeRPCRequest(ctx, req.GetDatabase(), "BatchCreateSessions", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.BatchCreateSessions(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) GetSession(ctx context.Context, req *spannerpb.GetSessionRequest) (*spannerpb.Session, error) { + if err := e.authorizeRPCRequest(ctx, req.GetName(), "GetSession", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.GetSession(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) ListSessions(ctx context.Context, req *spannerpb.ListSessionsRequest) (*spannerpb.ListSessionsResponse, error) { + if err := e.authorizeRPCRequest(ctx, req.GetDatabase(), "ListSessions", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.ListSessions(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) DeleteSession(ctx context.Context, req *spannerpb.DeleteSessionRequest) (*emptypb.Empty, error) { + if err := e.authorizeRPCRequest(ctx, req.GetName(), "DeleteSession", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.DeleteSession(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) ExecuteBatchDml(ctx context.Context, req *spannerpb.ExecuteBatchDmlRequest) (*spannerpb.ExecuteBatchDmlResponse, error) { + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "ExecuteBatchDml", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.ExecuteBatchDml(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) Read(ctx context.Context, req *spannerpb.ReadRequest) (*spannerpb.ResultSet, error) { + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "Read", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.Read(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) BeginTransaction(ctx context.Context, req *spannerpb.BeginTransactionRequest) (*spannerpb.Transaction, error) { + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "BeginTransaction", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.BeginTransaction(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) Commit(ctx context.Context, req *spannerpb.CommitRequest) (*spannerpb.CommitResponse, error) { + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "Commit", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.Commit(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) Rollback(ctx context.Context, req *spannerpb.RollbackRequest) (*emptypb.Empty, error) { + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "Rollback", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.Rollback(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) PartitionRead(ctx context.Context, req *spannerpb.PartitionReadRequest) (*spannerpb.PartitionResponse, error) { + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "PartitionRead", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.PartitionRead(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) BatchWrite(req *spannerpb.BatchWriteRequest, stream spannerpb.Spanner_BatchWriteServer) error { + ctx := stream.Context() + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "BatchWrite", req); err != nil { + return trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return trace.Wrap(err) + } + cc, err := clt.BatchWrite(ctx, req) + if err != nil { + return trace.Wrap(err) + } + return trace.Wrap(proxyServerStream(e.clientConnContext, cc, stream)) +} + +func (e *Engine) ExecuteSql(ctx context.Context, req *spannerpb.ExecuteSqlRequest) (*spannerpb.ResultSet, error) { + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "ExecuteSql", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.ExecuteSql(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) PartitionQuery(ctx context.Context, req *spannerpb.PartitionQueryRequest) (*spannerpb.PartitionResponse, error) { + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "PartitionQuery", req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + res, err := clt.PartitionQuery(ctx, req) + return res, trace.Wrap(err) +} + +func (e *Engine) ExecuteStreamingSql(req *spannerpb.ExecuteSqlRequest, stream spannerpb.Spanner_ExecuteStreamingSqlServer) error { + ctx := stream.Context() + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "ExecuteStreamingSql", req); err != nil { + return trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return trace.Wrap(err) + } + cc, err := clt.ExecuteStreamingSql(ctx, req) + if err != nil { + return trace.Wrap(err) + } + return trace.Wrap(proxyServerStream(e.clientConnContext, cc, stream)) +} + +func (e *Engine) StreamingRead(req *spannerpb.ReadRequest, stream spannerpb.Spanner_StreamingReadServer) error { + ctx := stream.Context() + if err := e.authorizeRPCRequest(ctx, req.GetSession(), "StreamingRead", req); err != nil { + return trace.Wrap(err) + } + clt, err := e.getClient(ctx) + if err != nil { + return trace.Wrap(err) + } + cc, err := clt.StreamingRead(ctx, req) + if err != nil { + return trace.Wrap(err) + } + return trace.Wrap(proxyServerStream(e.clientConnContext, cc, stream)) +} + +func (e *Engine) getClient(ctx context.Context) (spannerpb.SpannerClient, error) { + e.mu.Lock() + defer e.mu.Unlock() + clt, err := e.getClientLocked(ctx) + if err != nil { + e.cancelContext(err) + return nil, trace.Wrap(err) + } + return clt, nil +} + +func (e *Engine) getClientLocked(ctx context.Context) (spannerpb.SpannerClient, error) { + // re-use the connection if we already connected. + if e.gcloudClient != nil { + return spannerpb.NewSpannerClient(e.gcloudClient), nil + } + + tlsCfg, err := e.Auth.GetTLSConfig(ctx, e.sessionCtx) + if err != nil { + return nil, trace.Wrap(err) + } + + // get a token source for RPC auth. Assume (essentially require) that the + // db username is the portion of @.iam.gserviceaccount.com. + // TODO(gavin): should we relax the naming requirements? Is there ever a + // reason someone would want to use the full service account name, like for + // a service account in a different project? + dbUser := databaseUserToGCPServiceAccount(e.sessionCtx) + ts, err := e.Auth.GetSpannerTokenSource(e.clientConnContext, e.sessionCtx.WithUser(dbUser)) + if err != nil { + return nil, trace.Wrap(err) + } + + // The context passed to DialPool controls dialing, but more importantly it + // controls GCP oauth2 credential refreshing. + // We do not want credential refreshing to stop working after the first + // oauth token expires (by default after one hour). + // Therefore use the client connection context rather than the RPC context. + cc, err := gtransport.DialPool(e.clientConnContext, + append(spannerapi.DefaultClientOptions(), + option.WithGRPCDialOption(grpc.WithTransportCredentials(credentials.NewTLS(tlsCfg))), + option.WithGRPCDialOption(grpc.WithStatsHandler(&messageStatsHandler{ + messagesReceived: common.GetMessagesFromServerMetric(e.sessionCtx.Database), + })), + option.WithTokenSource(ts), + option.WithEndpoint(e.sessionCtx.Database.GetURI()), + // pool size seems to be adjusted to number of gRPC channels, which is + // 4 by default in Google's code and seemingly other clients as well, + // but with Teleport in the middle each downstream client connection + // will be handled by a separate engine. + // Therefore, avoid amplifying the number of connections dialed to + // GCP and just use a pool size of 1. + option.WithGRPCConnectionPool(1))..., + ) + if err != nil { + return nil, trace.Wrap(err) + } + + e.connSetupObserverFn() + e.gcloudClient = cc + return spannerpb.NewSpannerClient(e.gcloudClient), nil +} + +// authorizeRPCRequest checks authorization for an RPC and handles audit +// logging events based on the result of that check. +// +// Spanner IDs look like this: +// project ID: projects/ +// instance ID: /instances/ +// database ID: /databases/ +// session ID: /sessions/ +// +// All Spanner RPCs either include a database ID or a session ID. +// As outlined above, a session ID is prefixed by a database ID, and a database +// ID provides the target GCP project, instance, and database name. +// This function therefore expects a target ID that looks like +// `projects//instances//databases/[/sessions/[/sessions/] and returns the database name. +func parseDatabaseName(name string) (string, error) { + const ( + databasesPrefix = iota + database + numParts + ) + parts := strings.Split(name, "/") + if len(parts) < numParts || parts[databasesPrefix] != "databases" { + return "", trace.BadParameter("invalid database name") + } + return parts[database], nil +} + +func databaseUserToGCPServiceAccount(sessionCtx *common.Session) string { + return fmt.Sprintf("%s@%s.iam.gserviceaccount.com", + sessionCtx.DatabaseUser, + sessionCtx.Database.GetGCP().ProjectID, + ) +} + +// messageStatsHandler tracks messages received as a counter metric. +// Use it as a server option [grpc.Handler] to track messages received +// from a client. +// Use it as a dial option [grpc.WithHandler] to track messages received from a +// server. +type messageStatsHandler struct { + // messagesReceived tracks RPC payloads received. + messagesReceived prometheus.Counter +} + +func (s *messageStatsHandler) HandleRPC(ctx context.Context, rpcStats stats.RPCStats) { + if _, ok := rpcStats.(*stats.InPayload); ok { + s.messagesReceived.Inc() + } +} + +// TagRPC is a no-op for the message stats handler. +func (s *messageStatsHandler) TagRPC(ctx context.Context, _ *stats.RPCTagInfo) context.Context { + // no-op + return ctx +} + +// TagConn is a no-op for the message stats handler. +func (s *messageStatsHandler) TagConn(ctx context.Context, _ *stats.ConnTagInfo) context.Context { + return ctx +} + +// HandleConn is a no-op for the message stats handler. +func (s *messageStatsHandler) HandleConn(_ context.Context, _ stats.ConnStats) {} diff --git a/lib/srv/db/spanner/interceptors.go b/lib/srv/db/spanner/interceptors.go new file mode 100644 index 0000000000000..70c88d542fc9e --- /dev/null +++ b/lib/srv/db/spanner/interceptors.go @@ -0,0 +1,66 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package spanner + +import ( + "context" + + "github.com/sirupsen/logrus" + "google.golang.org/grpc" +) + +// unaryServerLoggingInterceptor is gRPC middleware that logs some debug info. +func unaryServerLoggingInterceptor(log logrus.FieldLogger) grpc.UnaryServerInterceptor { + return func( + ctx context.Context, + req interface{}, + info *grpc.UnaryServerInfo, + handler grpc.UnaryHandler, + ) (interface{}, error) { + res, err := handler(ctx, req) + logRPC(log, info.FullMethod, err) + return res, err + } +} + +// streamServerLoggingInterceptor is gRPC middleware that logs some debug info. +func streamServerLoggingInterceptor(log logrus.FieldLogger) grpc.StreamServerInterceptor { + return func( + srv interface{}, + stream grpc.ServerStream, + info *grpc.StreamServerInfo, + handler grpc.StreamHandler, + ) error { + err := handler(srv, stream) + logRPC(log, info.FullMethod, err) + return err + } +} + +func logRPC(log logrus.FieldLogger, fullMethod string, handlerErr error) { + if handlerErr != nil { + log.WithError(handlerErr). + WithField("full_method", fullMethod). + Debug("failed to handle Spanner RPC") + return + } + + log.WithField("full_method", fullMethod). + Trace("handled Spanner RPC") +} diff --git a/lib/srv/db/spanner/listener.go b/lib/srv/db/spanner/listener.go new file mode 100644 index 0000000000000..4beb86a899e23 --- /dev/null +++ b/lib/srv/db/spanner/listener.go @@ -0,0 +1,53 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package spanner + +import ( + "io" + "net" + "sync/atomic" +) + +// singleUseListener wraps a single [net.Conn] and returns it from Accept() +// once. +type singleUseListener struct { + conn net.Conn + accepted atomic.Bool +} + +func newSingleUseListener(c net.Conn) *singleUseListener { + return &singleUseListener{ + conn: c, + } +} + +func (l *singleUseListener) Accept() (net.Conn, error) { + if l.accepted.Swap(true) { + return nil, io.EOF + } + return l.conn, nil +} + +func (l *singleUseListener) Addr() net.Addr { + return l.conn.LocalAddr() +} + +func (l *singleUseListener) Close() error { + return nil +} diff --git a/lib/srv/db/spanner/test.go b/lib/srv/db/spanner/test.go new file mode 100644 index 0000000000000..4a7b5378766cd --- /dev/null +++ b/lib/srv/db/spanner/test.go @@ -0,0 +1,286 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package spanner + +import ( + "context" + "fmt" + "net" + "strconv" + "strings" + "time" + + "cloud.google.com/go/spanner" + "cloud.google.com/go/spanner/apiv1/spannerpb" + "github.com/google/uuid" + "github.com/gravitational/trace" + "github.com/sirupsen/logrus" + "google.golang.org/api/option" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/metadata" + "google.golang.org/protobuf/types/known/structpb" + + "github.com/gravitational/teleport" + apidefaults "github.com/gravitational/teleport/api/defaults" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/srv/db/common" + "github.com/gravitational/teleport/lib/tlsca" +) + +func MakeTestClient(ctx context.Context, config common.TestClientConfig) (*spanner.Client, error) { + return makeTestClient(ctx, config, false) +} + +func makeTestClient(ctx context.Context, config common.TestClientConfig, useTLS bool) (*spanner.Client, error) { + databaseID, err := getDatabaseID(ctx, config.RouteToDatabase, config.AuthServer) + if err != nil { + return nil, trace.Wrap(err) + } + + var transportOpt grpc.DialOption + if useTLS { + tlsCfg, err := common.MakeTestClientTLSConfig(config) + if err != nil { + return nil, trace.Wrap(err) + } + transportOpt = grpc.WithTransportCredentials(credentials.NewTLS(tlsCfg)) + } else { + transportOpt = grpc.WithTransportCredentials(insecure.NewCredentials()) + } + + opts := []option.ClientOption{ + // dial with custom transport security + option.WithGRPCDialOption(transportOpt), + // create 1 connection + option.WithGRPCConnectionPool(1), + // connect to the Teleport endpoint + option.WithEndpoint(config.Address), + // client should not bring any GCP credentials + option.WithoutAuthentication(), + } + + clientCfg := spanner.ClientConfig{ + SessionPoolConfig: spanner.DefaultSessionPoolConfig, + } + clt, err := spanner.NewClientWithConfig(ctx, databaseID, clientCfg, opts...) + if err != nil { + return nil, trace.Wrap(err) + } + return clt, nil +} + +func getDatabaseID(ctx context.Context, route tlsca.RouteToDatabase, getter services.DatabaseServersGetter) (string, error) { + const timeout = 10 * time.Second + const step = time.Second + + var server types.DatabaseServer + var err error + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + + for { + server, err = getDBServer(ctx, route.ServiceName, getter) + if err == nil { + break + } + select { + case <-ctx.Done(): + return "", trace.Wrap(err) + default: + } + time.Sleep(step) + } + + gcp := server.GetDatabase().GetGCP() + id := fmt.Sprintf("projects/%s/instances/%s/databases/%s", gcp.ProjectID, gcp.InstanceID, route.Database) + return id, nil +} + +func getDBServer(ctx context.Context, name string, getter services.DatabaseServersGetter) (types.DatabaseServer, error) { + servers, err := getter.GetDatabaseServers(ctx, apidefaults.Namespace) + if err != nil { + return nil, trace.Wrap(err) + } + for _, s := range servers { + if s.GetName() == name { + return s, nil + } + } + return nil, trace.NotFound("db_server %q not found", name) +} + +type TestServer struct { + srv *grpc.Server + listener net.Listener + port string + log logrus.FieldLogger + spannerpb.UnimplementedSpannerServer +} + +func NewTestServer(config common.TestServerConfig) (tsrv *TestServer, err error) { + err = config.CheckAndSetDefaults() + if err != nil { + return nil, trace.Wrap(err) + } + defer config.CloseOnError(&err) + + tlsConfig, err := common.MakeTestServerTLSConfig(config) + if err != nil { + return nil, trace.Wrap(err) + } + + port, err := config.Port() + if err != nil { + return nil, trace.Wrap(err) + } + + logger := logrus.WithFields(logrus.Fields{ + teleport.ComponentKey: defaults.ProtocolSpanner, + "name": config.Name, + }) + + checker := credentialChecker{expectToken: "Bearer " + config.AuthToken} + testServer := &TestServer{ + srv: grpc.NewServer( + grpc.Creds(credentials.NewTLS(tlsConfig)), + grpc.ChainUnaryInterceptor(unaryAuthInterceptor(checker)), + grpc.ChainStreamInterceptor(streamingAuthInterceptor(checker)), + ), + listener: config.Listener, + port: port, + log: logger, + } + spannerpb.RegisterSpannerServer(testServer.srv, testServer) + + return testServer, nil +} + +func unaryAuthInterceptor(c credentialChecker) grpc.UnaryServerInterceptor { + return func( + ctx context.Context, + req interface{}, + info *grpc.UnaryServerInfo, + handler grpc.UnaryHandler, + ) (interface{}, error) { + if err := c.check(ctx); err != nil { + return nil, trace.Wrap(err) + } + return handler(ctx, req) + } +} + +func streamingAuthInterceptor(c credentialChecker) grpc.StreamServerInterceptor { + return func( + srv interface{}, + stream grpc.ServerStream, + info *grpc.StreamServerInfo, + handler grpc.StreamHandler, + ) error { + if err := c.check(stream.Context()); err != nil { + return trace.Wrap(err) + } + return handler(srv, stream) + } +} + +type credentialChecker struct { + expectToken string +} + +func (c credentialChecker) check(ctx context.Context) error { + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return trace.AccessDenied("missing metadata") + } + tokens, ok := md["authorization"] + if !ok || len(tokens) < 1 { + return trace.AccessDenied("missing credentials in metadata") + } + if c.expectToken != tokens[0] { + return trace.AccessDenied("invalid RPC auth token. wanted: %q got: %q", c, tokens) + } + return nil +} + +func (s *TestServer) Serve() error { + return s.srv.Serve(s.listener) +} + +func (s *TestServer) Port() string { + return s.port +} + +func (s *TestServer) Close() error { + s.srv.GracefulStop() + return nil +} + +func (s *TestServer) BatchCreateSessions(ctx context.Context, req *spannerpb.BatchCreateSessionsRequest) (*spannerpb.BatchCreateSessionsResponse, error) { + tpl := req.SessionTemplate + if tpl == nil { + tpl = &spannerpb.Session{CreatorRole: "test"} + } + var sessions []*spannerpb.Session + for i := 0; i < int(req.SessionCount); i++ { + name := req.GetDatabase() + "/sessions/" + uuid.NewString() + sessions = append(sessions, &spannerpb.Session{ + Name: name, + Labels: tpl.Labels, + CreatorRole: tpl.CreatorRole, + Multiplexed: tpl.Multiplexed, + }) + } + res := &spannerpb.BatchCreateSessionsResponse{ + Session: sessions, + } + return res, nil +} + +func (s *TestServer) ExecuteStreamingSql(req *spannerpb.ExecuteSqlRequest, stream spannerpb.Spanner_ExecuteStreamingSqlServer) error { + q := strings.TrimSpace(strings.ToLower(req.GetSql())) + parts := strings.Split(q, " ") + if len(parts) != 2 || parts[0] != "select" { + return trace.BadParameter("test server only supports basic select statement") + } + _, err := strconv.ParseInt(parts[1], 10, 64) + if err != nil { + return trace.BadParameter("test server only supports selecting an int64") + } + + return stream.Send(&spannerpb.PartialResultSet{ + Metadata: &spannerpb.ResultSetMetadata{ + RowType: &spannerpb.StructType{ + Fields: []*spannerpb.StructType_Field{{ + Name: "", // no column name + Type: &spannerpb.Type{ + Code: spannerpb.TypeCode_INT64, + }, + }}, + }, + }, + Values: []*structpb.Value{ + // integers get encoded as a string in base 10. + structpb.NewStringValue(parts[1]), + }, + }) +} diff --git a/lib/srv/db/spanner_test.go b/lib/srv/db/spanner_test.go new file mode 100644 index 0000000000000..ca78f856b89e6 --- /dev/null +++ b/lib/srv/db/spanner_test.go @@ -0,0 +1,358 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package db + +import ( + "context" + "crypto/tls" + "fmt" + "net" + "testing" + "time" + + gspanner "cloud.google.com/go/spanner" + "github.com/stretchr/testify/require" + + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/types/events" + "github.com/gravitational/teleport/lib/defaults" + libevents "github.com/gravitational/teleport/lib/events" + "github.com/gravitational/teleport/lib/srv/db/common" + "github.com/gravitational/teleport/lib/srv/db/spanner" +) + +func TestAccessSpanner(t *testing.T) { + ctx := context.Background() + const dbServiceName = "my-spanner" + // matches the token from the mock Auth. + const authToken = "cloud-spanner-auth-token" + testCtx := setupTestContext(ctx, t, withSpanner(dbServiceName, authToken, func(db *types.DatabaseV3) { + db.SetStaticLabels(map[string]string{"foo": "bar"}) + })) + go testCtx.startHandlingConnections() + + dynamicDBLabels := types.Labels{"echo": {"test"}} + staticDBLabels := types.Labels{"foo": {"bar"}} + tests := []struct { + desc string + user string + role string + allowDbNames []string + allowDbUsers []string + extraRoleOpts []roleOptFn + dbName string + dbUser string + err string + }{ + { + desc: "has access to all database names and users", + user: "alice", + role: "admin", + allowDbNames: []string{types.Wildcard}, + allowDbUsers: []string{types.Wildcard}, + dbName: "googlesql", + dbUser: "admin", + }, + { + desc: "has access to nothing", + user: "alice", + role: "admin", + allowDbNames: []string{}, + allowDbUsers: []string{}, + dbName: "googlesql", + dbUser: "admin", + err: "access to db denied", + }, + { + desc: "no access to databases", + user: "alice", + role: "admin", + allowDbNames: []string{}, + allowDbUsers: []string{types.Wildcard}, + dbName: "googlesql", + dbUser: "admin", + err: "access to db denied", + }, + { + desc: "no access to users", + user: "alice", + role: "admin", + allowDbNames: []string{types.Wildcard}, + allowDbUsers: []string{}, + dbName: "googlesql", + dbUser: "admin", + err: "access to db denied", + }, + { + desc: "access allowed to specific user/database", + user: "alice", + role: "admin", + allowDbNames: []string{"googlesql"}, + allowDbUsers: []string{"alice"}, + dbName: "googlesql", + dbUser: "alice", + }, + { + desc: "access denied to specific user", + user: "alice", + role: "admin", + allowDbNames: []string{"googlesql"}, + allowDbUsers: []string{"alice"}, + dbName: "googlesql", + dbUser: "alice", + extraRoleOpts: []roleOptFn{withDeniedDatabaseUsers("alice")}, + err: "access to db denied", + }, + { + desc: "access denied to specific database", + user: "alice", + role: "admin", + allowDbNames: []string{"googlesql"}, + allowDbUsers: []string{"alice"}, + dbName: "googlesql", + dbUser: "alice", + extraRoleOpts: []roleOptFn{withDeniedDatabaseNames("googlesql")}, + err: "access to db denied", + }, + { + desc: "access allowed to specific user/database by static label", + user: "alice", + role: "admin", + allowDbNames: []string{"googlesql"}, + allowDbUsers: []string{"alice"}, + // The default test role created has wildcard labels allowed. + // This tests that specific allowed database labels matching the + // test database's static labels allows access. + extraRoleOpts: []roleOptFn{withAllowedDBLabels(staticDBLabels)}, + dbName: "googlesql", + dbUser: "alice", + }, + { + desc: "access allowed to specific user/database by dynamic label", + user: "alice", + role: "admin", + allowDbNames: []string{"googlesql"}, + allowDbUsers: []string{"alice"}, + // The default test role created has wildcard labels allowed. + // This tests that specific allowed database labels matching the + // test database's dynamic labels allows access, to ensure + // that RBAC checks against dynamic labels are working. + extraRoleOpts: []roleOptFn{withAllowedDBLabels(dynamicDBLabels)}, + dbName: "googlesql", + dbUser: "alice", + }, + { + desc: "access denied by dynamic label", + user: "alice", + role: "admin", + allowDbNames: []string{"googlesql"}, + allowDbUsers: []string{"alice"}, + // The default test role created has wildcard labels allowed. + // This tests that specific denied database labels matching the + // test database's dynamic labels denies access, to ensure + // that RBAC checks against dynamic labels are working. + extraRoleOpts: []roleOptFn{withDeniedDBLabels(dynamicDBLabels)}, + dbName: "googlesql", + dbUser: "alice", + err: "access to db denied", + }, + } + + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + // Create user/role with the requested permissions. + testCtx.createUserAndRole(ctx, t, test.user, test.role, + test.allowDbUsers, test.allowDbNames, test.extraRoleOpts...) + + // Try to connect to the database as this user. + clt, localProxy, err := testCtx.spannerClient(ctx, test.user, dbServiceName, test.dbUser, test.dbName) + // authz isn't checked until RPCs are sent, so we can't fail here. + require.NoError(t, err) + t.Cleanup(func() { + // Disconnect. + clt.Close() + _ = localProxy.Close() + }) + + // Execute a query. + row, err := pingSpanner(ctx, clt, 7) + if test.err != "" { + require.Error(t, err) + require.Contains(t, err.Error(), test.err) + return + } + require.NoError(t, err) + require.NotNil(t, row) + + var got int64 + require.NoError(t, row.Column(0, &got)) + require.Equal(t, int64(7), got) + }) + } +} + +func TestAuditSpanner(t *testing.T) { + ctx := context.Background() + const dbServiceName = "my-spanner" + // matches the token from the mock Auth. + const authToken = "cloud-spanner-auth-token" + testCtx := setupTestContext(ctx, t, withSpanner(dbServiceName, authToken, func(db *types.DatabaseV3) { + db.SetStaticLabels(map[string]string{"foo": "bar"}) + })) + go testCtx.startHandlingConnections() + + const ( + userName = "alice" + roleName = "admin" + allowedUser = "admin" + deniedUser = "notAdmin" + ) + testCtx.createUserAndRole(ctx, t, userName, roleName, []string{allowedUser}, []string{types.Wildcard}) + + t.Run("access denied", func(t *testing.T) { + // authz isn't checked until RPCs are sent, so we can't fail here. + clt, localProxy, err := testCtx.spannerClient(ctx, userName, dbServiceName, deniedUser, "googlesql") + require.NoError(t, err) + t.Cleanup(func() { + clt.Close() + _ = localProxy.Close() + }) + + require.NoError(t, err) + + row, err := pingSpanner(ctx, clt, 42) + require.Error(t, err) + require.ErrorContains(t, err, "access to db denied") + require.Nil(t, row) + + ev := requireEvent(t, testCtx, libevents.DatabaseSessionStartFailureCode) + dbStart1, ok := ev.(*events.DatabaseSessionStart) + require.True(t, ok) + require.Equal(t, "googlesql", dbStart1.DatabaseName) + + row, err = pingSpanner(ctx, clt, 42) + require.Error(t, err) + require.ErrorContains(t, err, "access to db denied") + require.Nil(t, row) + + ev = requireEvent(t, testCtx, libevents.DatabaseSessionStartFailureCode) + dbStart2, ok := ev.(*events.DatabaseSessionStart) + require.True(t, ok) + require.Equal(t, "googlesql", dbStart2.DatabaseName) + + // session start failure is sticky and causes the connection to shut + // down - a client should get the same error but Teleport shouldnt emit + // another start event for the same session, i.e. the client should be + // forced to reconnect for subsequent RPC attempts + require.NotEqual(t, dbStart1.SessionID, dbStart2.SessionID) + + // make sure no other events get emitted, including RPC failures, since + // a session was never started successfully. + select { + case evt := <-testCtx.emitter.C(): + require.FailNow(t, "an unexpected audit event was emitted", "got an audit event with code %v", evt.GetCode()) + case <-time.After(1 * time.Second): + } + }) + + t.Run("successful flow", func(t *testing.T) { + clt, localProxy, err := testCtx.spannerClient(ctx, userName, dbServiceName, allowedUser, "googlesql") + require.NoError(t, err) + t.Cleanup(func() { + clt.Close() + _ = localProxy.Close() + }) + + // Successful connection should trigger session start event and RPCs. + row, err := pingSpanner(ctx, clt, 42) + require.NoError(t, err) + require.NotNil(t, row) + var got int64 + require.NoError(t, row.Column(0, &got)) + require.Equal(t, int64(42), got) + + evt := requireEvent(t, testCtx, libevents.DatabaseSessionStartCode) + startEvt, ok := evt.(*events.DatabaseSessionStart) + require.True(t, ok) + require.Equal(t, "googlesql", startEvt.DatabaseName) + + rpcEvt := requireSpannerRPCEvent(t, testCtx) + require.Equal(t, "BatchCreateSessions", rpcEvt.Procedure) + require.Equal(t, "googlesql", rpcEvt.DatabaseName) + require.Equal(t, startEvt.SessionID, rpcEvt.SessionID) + + rpcEvt = requireSpannerRPCEvent(t, testCtx) + require.Equal(t, "ExecuteStreamingSql", rpcEvt.Procedure) + require.Equal(t, "googlesql", rpcEvt.DatabaseName) + require.Equal(t, startEvt.SessionID, rpcEvt.SessionID) + + // Client disconnects. + clt.Close() + _ = requireEvent(t, testCtx, libevents.DatabaseSessionEndCode) + }) +} + +func pingSpanner(ctx context.Context, clt *gspanner.Client, want int64) (*gspanner.Row, error) { + query := gspanner.NewStatement(fmt.Sprintf("SELECT %d", want)) + rowIter := clt.Single().Query(ctx, query) + defer rowIter.Stop() + + return rowIter.Next() +} + +func withSpanner(name, authToken string, dbOpts ...databaseOption) withDatabaseOption { + return func(t testing.TB, ctx context.Context, testCtx *testContext) types.Database { + spannerServer, err := spanner.NewTestServer(common.TestServerConfig{ + Name: name, + AuthClient: testCtx.authClient, + ClientAuth: tls.NoClientCert, // we are not using mTLS + AuthToken: authToken, + }) + require.NoError(t, err) + go spannerServer.Serve() + t.Cleanup(func() { spannerServer.Close() }) + + require.Len(t, testCtx.databaseCA.GetActiveKeys().TLS, 1) + ca := string(testCtx.databaseCA.GetActiveKeys().TLS[0].Cert) + + database, err := types.NewDatabaseV3(types.Metadata{ + Name: name, + }, types.DatabaseSpecV3{ + Protocol: defaults.ProtocolSpanner, + URI: net.JoinHostPort("localhost", spannerServer.Port()), + GCP: types.GCPCloudSQL{ + ProjectID: "project-id", + InstanceID: "instance-id", + }, + TLS: types.DatabaseTLS{ + CACert: ca, + }, + DynamicLabels: dynamicLabels, + }) + require.NoError(t, err) + for _, dbOpt := range dbOpts { + dbOpt(database) + } + testCtx.spanner[name] = testSpannerDB{ + db: spannerServer, + resource: database, + } + return database + } +} diff --git a/lib/teleterm/cmd/db.go b/lib/teleterm/cmd/db.go index b5f4ff2f63fa3..5c12fb73a38e6 100644 --- a/lib/teleterm/cmd/db.go +++ b/lib/teleterm/cmd/db.go @@ -64,8 +64,12 @@ func newDBCLICommandWithExecer(cluster *clusters.Cluster, gateway gateway.Gatewa dbcmd.WithExecer(execer), } - // DynamoDB doesn't support non-print-format use. - if gateway.Protocol() == defaults.ProtocolDynamoDB { + switch gateway.Protocol() { + case defaults.ProtocolDynamoDB, defaults.ProtocolSpanner: + // DynamoDB doesn't support non-print-format use. + // Spanner does, but it's not supported in Teleterm yet. + // TODO(gavin): get the database GCP metadata to enable spanner-cli in + // Teleterm. opts = append(opts, dbcmd.WithPrintFormat()) } diff --git a/lib/teleterm/cmd/db_test.go b/lib/teleterm/cmd/db_test.go index e080a0cff6cc9..cee79a64760e7 100644 --- a/lib/teleterm/cmd/db_test.go +++ b/lib/teleterm/cmd/db_test.go @@ -92,6 +92,12 @@ func TestNewDBCLICommand(t *testing.T) { protocol: defaults.ProtocolDynamoDB, checkCmds: checkArgsNotEmpty, }, + { + name: "custom handling of Spanner does not blow up", + targetSubresourceName: "bar", + protocol: defaults.ProtocolSpanner, + checkCmds: checkArgsNotEmpty, + }, } for _, tc := range testCases { diff --git a/tool/tsh/common/db.go b/tool/tsh/common/db.go index f429ee883cc10..47cf93a49248b 100644 --- a/tool/tsh/common/db.go +++ b/tool/tsh/common/db.go @@ -788,6 +788,9 @@ func onDatabaseConnect(cf *CLIConf) error { if opts, err = maybeAddDBUserPassword(cf, tc, dbInfo, opts); err != nil { return trace.Wrap(err) } + if opts, err = maybeAddGCPMetadata(cf.Context, tc, dbInfo, opts); err != nil { + return trace.Wrap(err) + } bb := dbcmd.NewCmdBuilder(tc, profile, dbInfo.RouteToDatabase, rootClusterName, opts...) cmd, err := bb.GetConnectCommand() @@ -1654,7 +1657,8 @@ func getDBLocalProxyRequirement(tc *client.TeleportClient, route tlsca.RouteToDa defaults.ProtocolSQLServer, defaults.ProtocolCassandra, defaults.ProtocolOracle, - defaults.ProtocolClickHouse: + defaults.ProtocolClickHouse, + defaults.ProtocolSpanner: // Some protocols only work in the local tunnel mode. out.addLocalProxyWithTunnel(formatDBProtocolReason(route.Protocol)) @@ -1748,12 +1752,7 @@ func formatDbCmdUnsupportedDBProtocol(cf *CLIConf, route tlsca.RouteToDatabase) // getDbCmdAlternatives is a helper func that returns alternative tsh commands for connecting to a database. func getDbCmdAlternatives(clusterFlag string, route tlsca.RouteToDatabase) []string { var alts []string - switch route.Protocol { - case defaults.ProtocolDynamoDB: - // DynamoDB only works with a local proxy tunnel and there is no "shell-like" cli, so `tsh db connect` doesn't make sense. - case defaults.ProtocolClickHouseHTTP: - // ClickHouse HTTP protocol don't support interactive mode - default: + if protocolSupportsInteractiveMode(route.Protocol) { // prefer displaying the connect command as the first suggested command alternative. alts = append(alts, formatDatabaseConnectCommand(clusterFlag, route)) } diff --git a/tool/tsh/common/proxy.go b/tool/tsh/common/proxy.go index 90d75949f98d1..58c010a3b97c8 100644 --- a/tool/tsh/common/proxy.go +++ b/tool/tsh/common/proxy.go @@ -19,6 +19,7 @@ package common import ( + "context" "crypto/tls" "crypto/x509/pkix" "fmt" @@ -234,6 +235,9 @@ func onProxyCommandDB(cf *CLIConf) error { if opts, err = maybeAddDBUserPassword(cf, tc, dbInfo, opts); err != nil { return trace.Wrap(err) } + if opts, err = maybeAddGCPMetadata(cf.Context, tc, dbInfo, opts); err != nil { + return trace.Wrap(err) + } commands, err := dbcmd.NewCmdBuilder(tc, profile, dbInfo.RouteToDatabase, rootCluster, opts..., @@ -250,8 +254,9 @@ func onProxyCommandDB(cf *CLIConf) error { "address": listener.Addr().String(), "randomPort": randomPort, } + maybeAddGCPMetadataTplArgs(cf.Context, tc, dbInfo, templateArgs) - tmpl := chooseProxyCommandTemplate(templateArgs, commands, dbInfo.Protocol) + tmpl := chooseProxyCommandTemplate(templateArgs, commands, dbInfo) err = tmpl.Execute(os.Stdout, templateArgs) if err != nil { return trace.Wrap(err) @@ -300,18 +305,55 @@ func maybeAddDBUserPassword(cf *CLIConf, tc *libclient.TeleportClient, dbInfo *d return opts, nil } +func requiresGCPMetadata(protocol string) bool { + return protocol == defaults.ProtocolSpanner +} + +func maybeAddGCPMetadata(ctx context.Context, tc *libclient.TeleportClient, dbInfo *databaseInfo, opts []dbcmd.ConnectCommandFunc) ([]dbcmd.ConnectCommandFunc, error) { + if !requiresGCPMetadata(dbInfo.Protocol) { + return opts, nil + } + db, err := dbInfo.GetDatabase(ctx, tc) + if err != nil { + return nil, trace.Wrap(err) + } + gcp := db.GetGCP() + return append(opts, dbcmd.WithGCP(gcp)), nil +} + +func maybeAddGCPMetadataTplArgs(ctx context.Context, tc *libclient.TeleportClient, dbInfo *databaseInfo, templateArgs map[string]any) { + if !requiresGCPMetadata(dbInfo.Protocol) { + return + } + templateArgs["gcpProject"] = "" + templateArgs["gcpInstance"] = "" + db, err := dbInfo.GetDatabase(ctx, tc) + if err == nil { + gcp := db.GetGCP() + templateArgs["gcpProject"] = gcp.ProjectID + templateArgs["gcpInstance"] = gcp.InstanceID + } +} + type templateCommandItem struct { Description string Command string } -func chooseProxyCommandTemplate(templateArgs map[string]any, commands []dbcmd.CommandAlternative, protocol string) *template.Template { +func chooseProxyCommandTemplate(templateArgs map[string]any, commands []dbcmd.CommandAlternative, dbInfo *databaseInfo) *template.Template { // there is only one command, use plain template. if len(commands) == 1 { templateArgs["command"] = formatCommand(commands[0].Command) - if protocol == defaults.ProtocolOracle { + switch dbInfo.Protocol { + case defaults.ProtocolOracle: templateArgs["args"] = commands[0].Command.Args return dbProxyOracleAuthTpl + case defaults.ProtocolSpanner: + templateArgs["databaseName"] = "" + if dbInfo.Database != "" { + templateArgs["databaseName"] = dbInfo.Database + } + return dbProxySpannerAuthTpl } return dbProxyAuthTpl } @@ -704,6 +746,19 @@ Use the following command to connect to the database or to the address above usi $ {{.command}} `)) +// dbProxySpannerAuthTpl is the message that's printed for an authenticated spanner db proxy. +var dbProxySpannerAuthTpl = template.Must(template.New("").Parse( + `Started authenticated tunnel for the {{.type}} database "{{.database}}" in cluster "{{.cluster}}" on {{.address}}. +{{if .randomPort}}To avoid port randomization, you can choose the listening port using the --port flag. +{{end}} +` + dbProxyConnectAd + ` +Use the following command to connect to the database or to the address above using other database GUI/CLI clients: + $ {{.command}} + +Or use the following JDBC connection string to connect with other GUI/CLI clients: +jdbc:cloudspanner://{{.address}}/projects/{{.gcpProject}}/instances/{{.gcpInstance}}/databases/{{.databaseName}};usePlainText=true +`)) + // dbProxyOracleAuthTpl is the message that's printed for an authenticated db proxy. var dbProxyOracleAuthTpl = template.Must(template.New("").Funcs(templateFunctions).Parse( `Started authenticated tunnel for the {{.type}} database "{{.database}}" in cluster "{{.cluster}}" on {{.address}}. diff --git a/tool/tsh/common/proxy_test.go b/tool/tsh/common/proxy_test.go index fb7f0a1e40603..18dce9fad66a6 100644 --- a/tool/tsh/common/proxy_test.go +++ b/tool/tsh/common/proxy_test.go @@ -1261,7 +1261,7 @@ Use one of the following commands to connect to the database or to the address a for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { templateArgs := map[string]any{} - tpl := chooseProxyCommandTemplate(templateArgs, tt.commands, "") + tpl := chooseProxyCommandTemplate(templateArgs, tt.commands, &databaseInfo{}) require.Equal(t, tt.wantTemplate, tpl) require.Equal(t, tt.wantTemplateArgs, templateArgs) diff --git a/web/packages/shared/services/databases/databases.ts b/web/packages/shared/services/databases/databases.ts index c4a19efc5f9fc..02147ddd3eed3 100644 --- a/web/packages/shared/services/databases/databases.ts +++ b/web/packages/shared/services/databases/databases.ts @@ -29,7 +29,8 @@ export type DbType = | 'keyspace' | 'cassandra' | 'dynamodb' - | 'opensearch'; + | 'opensearch' + | 'spanner'; export type DbProtocol = | 'postgres' @@ -45,7 +46,8 @@ export type DbProtocol = | 'opensearch' | 'dynamodb' | 'clickhouse' - | 'clickhouse-http'; + | 'clickhouse-http' + | 'spanner'; const formatProtocol = (input: DbProtocol) => { switch (input) { @@ -67,6 +69,8 @@ const formatProtocol = (input: DbProtocol) => { return 'Cassandra'; case 'elasticsearch': return 'Elasticsearch'; + case 'spanner': + return 'Spanner'; default: return input; } @@ -117,6 +121,9 @@ export const formatDatabaseInfo = (type: DbType, protocol: DbProtocol) => { case 'azure': output.title = `Azure ${formatProtocol(protocol)}`; return output; + case 'spanner': + output.title = 'Cloud Spanner'; + return output; default: output.title = `${type} ${formatProtocol(protocol)}`; return output; diff --git a/web/packages/teleport/src/Audit/EventList/EventTypeCell.tsx b/web/packages/teleport/src/Audit/EventList/EventTypeCell.tsx index 61d270ed8f263..34ed5b8b5c05d 100644 --- a/web/packages/teleport/src/Audit/EventList/EventTypeCell.tsx +++ b/web/packages/teleport/src/Audit/EventList/EventTypeCell.tsx @@ -181,6 +181,8 @@ const EventIconMap: Record = { [eventCodes.OPENSEARCH_REQUEST_FAILURE]: Icons.Database, [eventCodes.DYNAMODB_REQUEST]: Icons.Database, [eventCodes.DYNAMODB_REQUEST_FAILURE]: Icons.Database, + [eventCodes.SPANNER_RPC]: Icons.Database, + [eventCodes.SPANNER_RPC_DENIED]: Icons.Database, [eventCodes.DESKTOP_SESSION_STARTED]: Icons.Desktop, [eventCodes.DESKTOP_SESSION_STARTED_FAILED]: Icons.Desktop, [eventCodes.DESKTOP_SESSION_ENDED]: Icons.Desktop, diff --git a/web/packages/teleport/src/Audit/__snapshots__/Audit.story.test.tsx.snap b/web/packages/teleport/src/Audit/__snapshots__/Audit.story.test.tsx.snap index 1ae5dd052940a..4e283706ccef0 100644 --- a/web/packages/teleport/src/Audit/__snapshots__/Audit.story.test.tsx.snap +++ b/web/packages/teleport/src/Audit/__snapshots__/Audit.story.test.tsx.snap @@ -405,12 +405,12 @@ exports[`list of all events 1`] = ` - - 239 + 241 of - 239 + 241 + + + + +
+ + + + + + Spanner RPC +
+ + + User [alice@example.com] executed query [select * from TestTable] in database [dev-db] on [teleport-spanner] + + + 2024-03-13T00:02:44.739Z + + + + + ( /> ); +export const ConnectSpanner = () => ( + null} + authType="local" + /> +); + export const ConnectWithRequestId = () => { return ( { expect(screen.getByText(expectedOutput)).toBeInTheDocument(); }); +test('correct connect command generated for spanner', () => { + render(); + + // --db-name flag should be required + const expectedOutput = + 'tsh db connect gspanner --db-user= --db-name='; + + expect(screen.getByText(expectedOutput)).toBeInTheDocument(); +}); + test('correct connect command generated for mysql db', () => { render(); diff --git a/web/packages/teleport/src/Databases/ConnectDialog/ConnectDialog.tsx b/web/packages/teleport/src/Databases/ConnectDialog/ConnectDialog.tsx index 7d6427d0d8b1c..20394973f0459 100644 --- a/web/packages/teleport/src/Databases/ConnectDialog/ConnectDialog.tsx +++ b/web/packages/teleport/src/Databases/ConnectDialog/ConnectDialog.tsx @@ -53,6 +53,7 @@ export default function ConnectDialog({ case 'sqlserver': case 'oracle': case 'mongodb': + case 'spanner': // Required dbNameFlag = ' --db-name='; break; @@ -107,7 +108,7 @@ export default function ConnectDialog({ {' - Connect to the database'} ${dbNameFlag}`} + text={`tsh ${connectCommand} ${dbName} --db-user=${dbNameFlag}`} /> {accessRequestId && ( diff --git a/web/packages/teleport/src/Databases/ConnectDialog/__snapshots__/ConnectDialog.test.tsx.snap b/web/packages/teleport/src/Databases/ConnectDialog/__snapshots__/ConnectDialog.test.tsx.snap index 6bc6fca6cbcc1..5bb4b44c17efa 100644 --- a/web/packages/teleport/src/Databases/ConnectDialog/__snapshots__/ConnectDialog.test.tsx.snap +++ b/web/packages/teleport/src/Databases/ConnectDialog/__snapshots__/ConnectDialog.test.tsx.snap @@ -308,7 +308,7 @@ exports[`render dialog with instructions to connect to database 1`] = ` $
- tsh db connect aurora --db-user=<user> --db-name=<name> + tsh db connect aurora --db-user=<user> --db-name=<name>