diff --git a/api/client/client.go b/api/client/client.go index 5fbab4eb20776..fd0cf5aeb3fa0 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -2409,6 +2409,8 @@ func (c *Client) ListResources(ctx context.Context, req proto.ListResourcesReque resources[i] = respResource.GetNode() case types.KindKubeService: resources[i] = respResource.GetKubeService() + case types.KindWindowsDesktop: + resources[i] = respResource.GetWindowsDesktop() default: return nil, trace.NotImplemented("resource type %s does not support pagination", req.ResourceType) } diff --git a/api/client/client_test.go b/api/client/client_test.go index 5b67271ff7238..88b4fa3187600 100644 --- a/api/client/client_test.go +++ b/api/client/client_test.go @@ -121,6 +121,13 @@ func (m *mockServer) ListResources(ctx context.Context, req *proto.ListResources } protoResource = &proto.PaginatedResource{Resource: &proto.PaginatedResource_KubeService{KubeService: srv}} + case types.KindWindowsDesktop: + desktop, ok := resource.(*types.WindowsDesktopV3) + if !ok { + return nil, trace.Errorf("windows desktop has invalid type %T", resource) + } + + protoResource = &proto.PaginatedResource{Resource: &proto.PaginatedResource_WindowsDesktop{WindowsDesktop: desktop}} } resp.Resources = append(resp.Resources, protoResource) @@ -226,6 +233,21 @@ func testResources(resourceType, namespace string) ([]types.ResourceWithLabels, return nil, trace.Wrap(err) } } + case types.KindWindowsDesktop: + for i := 0; i < size; i++ { + var err error + name := fmt.Sprintf("windows-desktop-%d", i) + resources[i], err = types.NewWindowsDesktopV3( + name, + map[string]string{"label": string(make([]byte, labelSize))}, + types.WindowsDesktopSpecV3{ + Addr: "_", + HostID: "_", + }) + if err != nil { + return nil, trace.Wrap(err) + } + } default: return nil, trace.Errorf("unsupported resource type %s", resourceType) @@ -479,6 +501,10 @@ func TestListResources(t *testing.T) { resourceType: types.KindKubeService, resourceStruct: &types.ServerV2{}, }, + "WindowsDesktop": { + resourceType: types.KindWindowsDesktop, + resourceStruct: &types.WindowsDesktopV3{}, + }, } // Create client @@ -558,6 +584,9 @@ func TestGetResources(t *testing.T) { "KubeService": { resourceType: types.KindKubeService, }, + "WindowsDesktop": { + resourceType: types.KindWindowsDesktop, + }, } for name, test := range testCases { diff --git a/api/client/proto/authservice.pb.go b/api/client/proto/authservice.pb.go index 954de3239f987..186c644d65cde 100644 --- a/api/client/proto/authservice.pb.go +++ b/api/client/proto/authservice.pb.go @@ -9140,6 +9140,7 @@ type PaginatedResource struct { // *PaginatedResource_AppServer // *PaginatedResource_Node // *PaginatedResource_KubeService + // *PaginatedResource_WindowsDesktop Resource isPaginatedResource_Resource `protobuf_oneof:"resource"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -9197,11 +9198,15 @@ type PaginatedResource_Node struct { type PaginatedResource_KubeService struct { KubeService *types.ServerV2 `protobuf:"bytes,4,opt,name=KubeService,proto3,oneof" json:"kube_service,omitempty"` } +type PaginatedResource_WindowsDesktop struct { + WindowsDesktop *types.WindowsDesktopV3 `protobuf:"bytes,5,opt,name=WindowsDesktop,proto3,oneof" json:"windows_desktop,omitempty"` +} func (*PaginatedResource_DatabaseServer) isPaginatedResource_Resource() {} func (*PaginatedResource_AppServer) isPaginatedResource_Resource() {} func (*PaginatedResource_Node) isPaginatedResource_Resource() {} func (*PaginatedResource_KubeService) isPaginatedResource_Resource() {} +func (*PaginatedResource_WindowsDesktop) isPaginatedResource_Resource() {} func (m *PaginatedResource) GetResource() isPaginatedResource_Resource { if m != nil { @@ -9238,6 +9243,13 @@ func (m *PaginatedResource) GetKubeService() *types.ServerV2 { return nil } +func (m *PaginatedResource) GetWindowsDesktop() *types.WindowsDesktopV3 { + if x, ok := m.GetResource().(*PaginatedResource_WindowsDesktop); ok { + return x.WindowsDesktop + } + return nil +} + // XXX_OneofWrappers is for the internal use of the proto package. func (*PaginatedResource) XXX_OneofWrappers() []interface{} { return []interface{}{ @@ -9245,6 +9257,7 @@ func (*PaginatedResource) XXX_OneofWrappers() []interface{} { (*PaginatedResource_AppServer)(nil), (*PaginatedResource_Node)(nil), (*PaginatedResource_KubeService)(nil), + (*PaginatedResource_WindowsDesktop)(nil), } } @@ -9271,10 +9284,12 @@ type ListResourcesRequest struct { SortBy types.SortBy `protobuf:"bytes,8,opt,name=SortBy,proto3" json:"sort_by,omitempty"` // NeedTotalCount indicates whether or not the caller also wants the total number of resources // after filtering. - NeedTotalCount bool `protobuf:"varint,9,opt,name=NeedTotalCount,proto3" json:"need_total_count,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + NeedTotalCount bool `protobuf:"varint,9,opt,name=NeedTotalCount,proto3" json:"need_total_count,omitempty"` + // WindowsDesktopFilter specifies windows desktop specific filters. + WindowsDesktopFilter types.WindowsDesktopFilter `protobuf:"bytes,10,opt,name=WindowsDesktopFilter,proto3" json:"windows_desktop_filter,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *ListResourcesRequest) Reset() { *m = ListResourcesRequest{} } @@ -9373,6 +9388,13 @@ func (m *ListResourcesRequest) GetNeedTotalCount() bool { return false } +func (m *ListResourcesRequest) GetWindowsDesktopFilter() types.WindowsDesktopFilter { + if m != nil { + return m.WindowsDesktopFilter + } + return types.WindowsDesktopFilter{} +} + // ListResourceResponse response of ListResources. type ListResourcesResponse struct { // Resources is a list of resource. @@ -10266,13 +10288,13 @@ func init() { func init() { proto.RegisterFile("authservice.proto", fileDescriptor_ce8bd90b12161215) } var fileDescriptor_ce8bd90b12161215 = []byte{ - // 9391 bytes of a gzipped FileDescriptorProto + // 9423 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x7d, 0x5b, 0x6c, 0x1b, 0xc9, 0x96, 0x98, 0x49, 0xbd, 0xc8, 0xa3, 0x87, 0xe9, 0x92, 0x64, 0xd1, 0xb4, 0x2c, 0x7a, 0xda, 0x33, 0xbe, 0x9e, 0xd9, 0x59, 0xdb, 0x23, 0xcd, 0xfb, 0x79, 0x49, 0x4a, 0x96, 0x64, 0xcb, 0xb2, 0xa6, 0x29, 0xd1, 0x93, 0x7b, 0x67, 0xc3, 0x69, 0x91, 0x65, 0xa9, 0x23, 0x8a, 0xcd, 0xdb, 0xdd, 0xb4, - 0xc7, 0x08, 0x12, 0xe4, 0xb5, 0x49, 0x10, 0x20, 0xc0, 0x06, 0xc8, 0x22, 0x09, 0xf2, 0x91, 0xc5, - 0x26, 0x40, 0x90, 0x04, 0xfb, 0x13, 0x04, 0xf9, 0xcc, 0x57, 0x80, 0xdc, 0x04, 0x08, 0x92, 0x9f, + 0xc7, 0x08, 0x12, 0xe4, 0xb1, 0x9b, 0x04, 0x01, 0x02, 0x6c, 0x80, 0x2c, 0x92, 0x20, 0x1f, 0x59, + 0x6c, 0xf2, 0x93, 0x04, 0xfb, 0x13, 0x04, 0xf9, 0xcc, 0x57, 0x80, 0xdc, 0x04, 0x08, 0x92, 0x9f, 0x45, 0x80, 0xfd, 0xe0, 0x6e, 0xee, 0xa7, 0x7e, 0x83, 0x04, 0xc8, 0xfd, 0x0a, 0xea, 0xd9, 0x55, 0xdd, 0x5d, 0xa4, 0x64, 0x3b, 0x77, 0x7f, 0x6c, 0xf5, 0xa9, 0x3a, 0xa7, 0xaa, 0x4e, 0x9d, 0x3a, 0x75, 0xea, 0xd4, 0xa9, 0x43, 0xb8, 0xe2, 0xf4, 0xc3, 0xe3, 0x00, 0xfb, 0xcf, 0xdd, 0x16, 0xbe, @@ -10319,10 +10341,10 @@ var fileDescriptor_ce8bd90b12161215 = []byte{ 0xda, 0x5a, 0xd4, 0x0b, 0x1b, 0x6b, 0x6c, 0x2d, 0xb6, 0x39, 0xb4, 0x99, 0x22, 0x2f, 0x31, 0x7a, 0x84, 0x23, 0xd1, 0xc0, 0x8b, 0x68, 0x04, 0x47, 0x5e, 0xe0, 0xc3, 0x74, 0x8e, 0x44, 0x55, 0xd1, 0x16, 0xe4, 0x9e, 0xe2, 0x43, 0xa6, 0x39, 0xe6, 0x29, 0xbd, 0x2b, 0x11, 0x3d, 0xa6, 0x33, 0xd6, - 0xd8, 0xaa, 0x20, 0xd4, 0x92, 0xda, 0x42, 0x62, 0xa3, 0xdf, 0xcd, 0xc0, 0x92, 0x58, 0xe1, 0x38, + 0xd8, 0xaa, 0x20, 0xd4, 0x92, 0xda, 0x42, 0x62, 0xa3, 0xdf, 0xcb, 0xc0, 0x92, 0x58, 0xe1, 0x38, 0x7c, 0xe1, 0xf9, 0x27, 0x6e, 0xf7, 0xa8, 0xe6, 0x75, 0x9f, 0xb9, 0x47, 0xc5, 0x05, 0x4a, 0xf9, 0x66, 0x4c, 0x69, 0xc4, 0x6a, 0x35, 0x56, 0xab, 0x3f, 0x39, 0x1b, 0x94, 0x6f, 0x49, 0x05, 0x22, - 0xcb, 0x89, 0x40, 0x3e, 0x73, 0x8f, 0xb4, 0x86, 0x4d, 0x6d, 0xa1, 0xbf, 0x9e, 0x81, 0xab, 0x7c, + 0xcb, 0x89, 0x40, 0x3e, 0x73, 0x8f, 0xb4, 0x86, 0x4d, 0x6d, 0xa1, 0xbf, 0x99, 0x81, 0xab, 0x7c, 0x74, 0x36, 0x6e, 0x79, 0x7e, 0x3b, 0xea, 0xc6, 0x22, 0xed, 0x46, 0x59, 0xae, 0xd6, 0xb4, 0x4a, 0x8d, 0xd5, 0xea, 0xed, 0xb3, 0x41, 0xd9, 0xe2, 0x8c, 0x6b, 0xfa, 0xa2, 0x38, 0xad, 0x13, 0x86, 0x86, 0x88, 0x24, 0x10, 0xe5, 0xbf, 0xe7, 0xe3, 0x67, 0xd8, 0xc7, 0xdd, 0x16, 0x2e, 0x5e, 0xd5, @@ -10332,7 +10354,7 @@ var fileDescriptor_ce8bd90b12161215 = []byte{ 0x96, 0x42, 0x9c, 0x68, 0xde, 0x1d, 0xaf, 0x75, 0x52, 0x2c, 0x6a, 0x9a, 0x97, 0x80, 0x84, 0xca, 0xee, 0x78, 0xad, 0x13, 0x5d, 0xf3, 0x92, 0x52, 0x14, 0xc2, 0x3c, 0x9f, 0x25, 0x1b, 0x07, 0xa1, 0xef, 0x52, 0xdd, 0x11, 0x14, 0xaf, 0x51, 0x3a, 0xcb, 0x42, 0x07, 0x27, 0x6b, 0x34, 0x3e, 0x64, - 0xbd, 0xe5, 0x82, 0xd0, 0xf4, 0x95, 0x32, 0xad, 0x99, 0x34, 0xf2, 0xe8, 0xaf, 0xc0, 0xe2, 0x53, + 0xbd, 0xe5, 0x82, 0xd0, 0xf4, 0x95, 0x32, 0xad, 0x99, 0x34, 0xf2, 0xe8, 0xaf, 0xc1, 0xe2, 0x53, 0xb7, 0xdb, 0xf6, 0x5e, 0x04, 0xeb, 0x38, 0x38, 0x09, 0xbd, 0x5e, 0x9d, 0x59, 0x7e, 0xc5, 0x12, 0x6d, 0x77, 0x45, 0x88, 0x79, 0x5a, 0x9d, 0xc6, 0x5a, 0xf5, 0x9d, 0xb3, 0x41, 0xf9, 0xad, 0x17, 0xac, 0xb0, 0xd9, 0x66, 0xa5, 0x4d, 0x6e, 0x3c, 0x6a, 0x8d, 0xa7, 0xb7, 0x42, 0x44, 0x40, 0x2f, @@ -10370,12 +10392,12 @@ var fileDescriptor_ce8bd90b12161215 = []byte{ 0x76, 0xbe, 0x7a, 0xf9, 0x6c, 0x50, 0x9e, 0xe6, 0xb6, 0x8c, 0xd3, 0x6e, 0xfb, 0xb6, 0x52, 0x05, 0xd5, 0x20, 0x67, 0x7b, 0x8c, 0xc1, 0xdc, 0xb0, 0xbe, 0x2c, 0x0d, 0x6b, 0x06, 0xe6, 0x47, 0x29, 0xfe, 0xa5, 0x8e, 0x52, 0xd4, 0x40, 0x65, 0x98, 0xda, 0xf5, 0x6a, 0x4e, 0xeb, 0x98, 0x99, 0xd7, - 0xb9, 0xea, 0xc4, 0xd9, 0xa0, 0x9c, 0xf9, 0x6d, 0x5b, 0x40, 0xad, 0x7f, 0x91, 0x83, 0x02, 0xb1, + 0xb9, 0xea, 0xc4, 0xd9, 0xa0, 0x9c, 0xf9, 0x6d, 0x5b, 0x40, 0xad, 0x7f, 0x99, 0x83, 0x02, 0xb1, 0xe1, 0x35, 0x89, 0x7a, 0x1f, 0xf2, 0xac, 0xef, 0x8f, 0xb8, 0x60, 0xce, 0x54, 0xe7, 0xce, 0x06, 0x65, 0xe0, 0x03, 0x24, 0x83, 0x8b, 0x2a, 0xa0, 0x3b, 0x90, 0x23, 0x14, 0xba, 0x91, 0x68, 0xcd, 0x9c, 0x0d, 0xca, 0xb9, 0x3e, 0x87, 0xd9, 0xb2, 0x14, 0xd5, 0x61, 0x6a, 0xe3, 0xc7, 0x9e, 0xeb, 0xe3, 0x80, 0x1f, 0xe5, 0x4a, 0x77, 0xd9, 0x89, 0xfd, 0xae, 0x38, 0xb1, 0xdf, 0xdd, 0x17, 0x27, - 0xf6, 0xea, 0x0d, 0xae, 0x42, 0xae, 0x60, 0x86, 0x12, 0x8d, 0xef, 0xf7, 0xfe, 0xb4, 0x9c, 0xb1, + 0xf6, 0xea, 0x0d, 0xae, 0x42, 0xae, 0x60, 0x86, 0x12, 0x8d, 0xef, 0xf7, 0xff, 0xac, 0x9c, 0xb1, 0x05, 0x25, 0xf4, 0x3e, 0x4c, 0x3e, 0xf0, 0xfc, 0x53, 0x27, 0xa4, 0x27, 0xb8, 0x3c, 0x5f, 0xae, 0x14, 0xa2, 0x2d, 0x57, 0x0a, 0x41, 0x0f, 0x60, 0xce, 0xf6, 0xfa, 0x21, 0xde, 0xf7, 0x84, 0xb9, 0xc9, 0x56, 0xed, 0xca, 0xd9, 0xa0, 0x5c, 0xf2, 0x49, 0x49, 0x33, 0xf4, 0x92, 0x86, 0xa5, 0x1d, @@ -10389,7 +10411,7 @@ var fileDescriptor_ce8bd90b12161215 = []byte{ 0x58, 0x9d, 0x27, 0x3b, 0x48, 0x9f, 0xfc, 0xa9, 0xee, 0x20, 0xb4, 0x0c, 0x7d, 0x0b, 0xc0, 0x7b, 0x45, 0x76, 0xb6, 0x69, 0xbe, 0xd7, 0x6a, 0x83, 0x24, 0x9b, 0xd8, 0x0a, 0x1f, 0xdf, 0x55, 0x39, 0x3e, 0x6d, 0xaf, 0xb3, 0x15, 0x22, 0xe8, 0x1b, 0x98, 0xa1, 0xea, 0x4a, 0xcc, 0xe8, 0x0c, 0x9d, - 0x51, 0x7a, 0xf4, 0x27, 0x0a, 0x30, 0x6d, 0x3e, 0x35, 0x04, 0xf4, 0x57, 0x61, 0x91, 0x93, 0x8b, + 0x51, 0x7a, 0xf4, 0x27, 0x0a, 0x30, 0x6d, 0x3e, 0x35, 0x04, 0xf4, 0xd7, 0x61, 0x91, 0x93, 0x8b, 0x99, 0x19, 0xb3, 0xdc, 0xac, 0xd2, 0xba, 0xa7, 0xd7, 0xa9, 0xbe, 0xc7, 0x7b, 0x6a, 0xc9, 0x9e, 0x1a, 0x0d, 0x0f, 0x3b, 0xbd, 0x19, 0xeb, 0x3b, 0xc8, 0x4b, 0xe6, 0xa1, 0x29, 0x18, 0xab, 0x74, 0x3a, 0x85, 0x4b, 0xe4, 0x8f, 0x7a, 0x7d, 0xab, 0x90, 0x41, 0x73, 0x00, 0x91, 0xc4, 0x14, 0xb2, @@ -10412,448 +10434,450 @@ var fileDescriptor_ce8bd90b12161215 = []byte{ 0xa8, 0x9e, 0xd8, 0x02, 0x98, 0x35, 0x6c, 0xf2, 0xb4, 0x50, 0xc1, 0x89, 0x6d, 0x0d, 0xf1, 0x0d, 0xc1, 0x3a, 0x80, 0xd9, 0xbd, 0x4e, 0xff, 0xc8, 0xed, 0x12, 0x01, 0xad, 0xe3, 0x5f, 0xa0, 0x75, 0x80, 0x08, 0xc0, 0x5b, 0x10, 0xee, 0x85, 0xa8, 0xa0, 0xb1, 0xc6, 0xa7, 0x98, 0x42, 0xa8, 0x0e, - 0xb7, 0x15, 0x3c, 0xeb, 0xef, 0x8d, 0x01, 0xe2, 0x6d, 0xd4, 0x43, 0x27, 0xc4, 0x75, 0x1c, 0x92, + 0xb7, 0x15, 0x3c, 0xeb, 0xef, 0x8f, 0x01, 0xe2, 0x6d, 0xd4, 0x43, 0x27, 0xc4, 0x75, 0x1c, 0x92, 0xed, 0xe2, 0x2a, 0x64, 0xa5, 0xd9, 0x38, 0x79, 0x36, 0x28, 0x67, 0xdd, 0xb6, 0x9d, 0xdd, 0x5e, 0x47, 0x1f, 0xc2, 0x04, 0xad, 0x46, 0x79, 0x3d, 0x27, 0xdb, 0x53, 0x29, 0x30, 0x99, 0x0e, 0xc8, 0x9f, 0x36, 0xab, 0x8c, 0x3e, 0x82, 0xfc, 0x3a, 0xee, 0xe0, 0x23, 0x27, 0xf4, 0x84, 0xdc, 0x31, 0x43, 0x4c, 0x00, 0x95, 0x29, 0x8a, 0x6a, 0x92, 0x0d, 0xdc, 0xc6, 0x4e, 0xe0, 0x75, 0xd5, 0x0d, - 0xdc, 0xa7, 0x10, 0x75, 0x03, 0x67, 0x75, 0xd0, 0xef, 0x67, 0x60, 0xba, 0xd2, 0xed, 0x72, 0x03, + 0xdc, 0xa7, 0x10, 0x75, 0x03, 0x67, 0x75, 0xd0, 0x1f, 0x64, 0x60, 0xba, 0xd2, 0xed, 0x72, 0x03, 0x27, 0xe0, 0xae, 0xd5, 0xc5, 0xbb, 0xd2, 0x33, 0xbe, 0xe3, 0x1c, 0xe2, 0x4e, 0x83, 0x98, 0xcc, - 0x41, 0xf5, 0x7b, 0xa2, 0x53, 0xff, 0x64, 0x50, 0xfe, 0xe2, 0x55, 0x9c, 0xed, 0x77, 0xf7, 0x7d, + 0x41, 0xf5, 0x7b, 0xa2, 0x53, 0xff, 0x74, 0x50, 0xfe, 0xe2, 0x55, 0x9c, 0xed, 0x77, 0xf7, 0x7d, 0xc7, 0x0d, 0x03, 0xea, 0xc7, 0x8a, 0x1a, 0x54, 0xc5, 0x4c, 0xe9, 0x07, 0x7a, 0x17, 0x26, 0x88, 0x7c, 0x0b, 0x3b, 0x80, 0x4e, 0x36, 0x59, 0x07, 0xda, 0xe1, 0x87, 0xd6, 0xb0, 0x6e, 0x41, 0x9e, 0x73, 0x72, 0x7b, 0xdd, 0x34, 0x05, 0xd6, 0x3a, 0xdc, 0xa0, 0x56, 0x1c, 0x26, 0x92, 0x4b, 0xbd, 0x39, 0x5c, 0x12, 0x23, 0xb3, 0x7f, 0x8a, 0x82, 0x25, 0x36, 0x9d, 0x10, 0xea, 0x0d, 0xb2, 0x45, 0x89, 0x55, 0x83, 0xe5, 0x4d, 0x1c, 0xda, 0x38, 0xc0, 0xe1, 0x9e, 0x13, 0x04, 0x2f, 0x3c, 0xbf, - 0x4d, 0x8b, 0x2e, 0x44, 0xe4, 0x6f, 0x65, 0xa0, 0x5c, 0xf3, 0x31, 0x99, 0x69, 0x23, 0xa1, 0xe1, - 0x2b, 0x78, 0x99, 0x5f, 0x2e, 0x64, 0xa3, 0x52, 0xc2, 0x6b, 0x7e, 0x81, 0xf0, 0x0e, 0x8c, 0xed, - 0xef, 0xef, 0x50, 0x89, 0x19, 0xa3, 0x8c, 0x1b, 0x0b, 0xc3, 0xce, 0xaf, 0x07, 0xe5, 0xdc, 0x7a, - 0x9f, 0x5d, 0x3e, 0xd8, 0xa4, 0xdc, 0x7a, 0x06, 0x8b, 0x36, 0xee, 0xe2, 0x17, 0xce, 0x61, 0x07, - 0x6b, 0xe6, 0x6a, 0x19, 0x26, 0x98, 0xb3, 0x2c, 0x31, 0x04, 0x06, 0xd7, 0xed, 0xd9, 0xec, 0x08, - 0x7b, 0xd6, 0xfa, 0x83, 0x0c, 0x14, 0xd8, 0x70, 0xab, 0x5e, 0x78, 0xbe, 0xf1, 0xf1, 0x11, 0x64, - 0x87, 0x8f, 0x00, 0xdd, 0x8e, 0xb8, 0x3d, 0x16, 0x6d, 0x7e, 0xb4, 0xab, 0x44, 0x87, 0x8b, 0x42, - 0x32, 0x20, 0x26, 0x4b, 0xec, 0x68, 0x44, 0x07, 0x44, 0x65, 0x49, 0x48, 0xd0, 0x1f, 0x65, 0xe1, - 0x8a, 0xd2, 0xc5, 0xa0, 0xe7, 0x75, 0x03, 0x4c, 0xce, 0x78, 0x44, 0x58, 0x94, 0x7e, 0xd2, 0x33, - 0x1e, 0xd9, 0x32, 0x9b, 0x91, 0x25, 0x4e, 0x3b, 0xfc, 0x2e, 0x39, 0x5c, 0x74, 0x12, 0xc7, 0x41, - 0xaa, 0xb8, 0x59, 0x55, 0x51, 0x7c, 0xee, 0x4e, 0xdf, 0x83, 0x1c, 0xfd, 0x93, 0x30, 0x62, 0xdc, - 0xcc, 0x08, 0x59, 0x09, 0xb9, 0x00, 0x0f, 0x3d, 0xb7, 0xfb, 0x18, 0x87, 0xc7, 0x9e, 0x38, 0x3c, - 0x6f, 0x13, 0x25, 0xf6, 0x97, 0x3c, 0xb7, 0xdb, 0x3c, 0xa5, 0xe0, 0x8b, 0x1e, 0x3a, 0x23, 0x82, - 0xb6, 0x42, 0xdc, 0xba, 0x0f, 0x05, 0xa2, 0x6f, 0xce, 0x3f, 0xa3, 0xd6, 0x02, 0xa0, 0x4d, 0x1c, - 0x56, 0x3d, 0x6d, 0xe3, 0xb0, 0x66, 0x61, 0x7a, 0xcf, 0xed, 0x1e, 0x89, 0xcf, 0x7f, 0x9f, 0x85, - 0x19, 0xf6, 0xcd, 0x67, 0x20, 0xb6, 0x93, 0x66, 0xce, 0xb3, 0x93, 0x7e, 0x0a, 0xb3, 0xdc, 0x9d, - 0x83, 0x7d, 0xea, 0x42, 0x66, 0xf3, 0x41, 0x4f, 0x94, 0xcc, 0xab, 0xd3, 0x7c, 0xce, 0x4a, 0x6c, - 0xbd, 0x22, 0xda, 0x81, 0x39, 0x06, 0x78, 0x80, 0x9d, 0xb0, 0x1f, 0x9d, 0xaa, 0x2e, 0x73, 0x3b, - 0x53, 0x80, 0x99, 0x32, 0xe2, 0xb4, 0x9e, 0x71, 0xa0, 0x1d, 0xc3, 0x45, 0xdf, 0xc0, 0xe5, 0x3d, - 0xdf, 0xfb, 0xf1, 0xa5, 0x62, 0x3b, 0x30, 0x7d, 0xbc, 0x48, 0x0e, 0x61, 0x3d, 0x52, 0xd4, 0x54, - 0x2d, 0x88, 0x78, 0x6d, 0x22, 0x53, 0xdb, 0x41, 0xd5, 0xf3, 0xdd, 0xee, 0x11, 0x9d, 0xcd, 0x1c, - 0x93, 0x29, 0x37, 0x68, 0x1e, 0x52, 0xa0, 0x2d, 0x8b, 0xad, 0x3f, 0x1c, 0x83, 0x9c, 0x6c, 0xf8, - 0xae, 0x6a, 0x96, 0xf2, 0xcd, 0x98, 0x2e, 0xcf, 0xe8, 0xf0, 0x63, 0x2b, 0x35, 0xd0, 0x35, 0xe6, - 0xcc, 0x62, 0x66, 0xc0, 0x14, 0x91, 0x31, 0xa7, 0xd7, 0xa3, 0x2e, 0x2b, 0xa2, 0x4c, 0xd7, 0xab, - 0x94, 0x0b, 0x39, 0xa6, 0x4c, 0xdb, 0x87, 0x76, 0x76, 0xbd, 0x4a, 0xe6, 0xfa, 0xc9, 0xf6, 0x7a, - 0x8d, 0x0e, 0x28, 0xc7, 0xe6, 0xda, 0x73, 0xdb, 0x2d, 0x9b, 0x42, 0x49, 0x69, 0xbd, 0xf2, 0x78, - 0x87, 0x77, 0x9a, 0x96, 0x06, 0xce, 0x69, 0xc7, 0xa6, 0x50, 0x62, 0x07, 0xb2, 0x3d, 0xba, 0xe6, - 0x75, 0x43, 0xdf, 0xeb, 0x04, 0xd4, 0x55, 0x90, 0xd3, 0xb6, 0xf3, 0x16, 0x2f, 0xb2, 0x63, 0x55, - 0xd1, 0x53, 0x58, 0xaa, 0xb4, 0x9f, 0x3b, 0xdd, 0x16, 0x6e, 0xb3, 0x92, 0xa7, 0x9e, 0x7f, 0xf2, - 0xac, 0xe3, 0xbd, 0x08, 0xe8, 0x29, 0x2f, 0xc7, 0xcf, 0x8b, 0xbc, 0x4a, 0x93, 0x93, 0x7b, 0x21, - 0x2a, 0xd9, 0x26, 0x6c, 0xa2, 0x22, 0x6a, 0x1d, 0xaf, 0xdf, 0xa6, 0xc7, 0xbb, 0x1c, 0x53, 0x11, - 0x2d, 0x02, 0xb0, 0x19, 0x9c, 0x70, 0x69, 0xab, 0xfe, 0x98, 0x9e, 0xce, 0x38, 0x97, 0x8e, 0x83, - 0x53, 0x9b, 0xc0, 0xd0, 0x3b, 0x30, 0x25, 0x4c, 0x5a, 0xe6, 0x14, 0xa0, 0x1e, 0x23, 0x61, 0xca, - 0x8a, 0x32, 0xeb, 0x03, 0xb8, 0xc2, 0x16, 0xcd, 0xb9, 0x2d, 0x35, 0x6b, 0x0f, 0xa0, 0x8e, 0x4f, - 0x9d, 0xde, 0xb1, 0x47, 0x26, 0xb6, 0xaa, 0x7e, 0x71, 0xd3, 0x05, 0x49, 0x47, 0x3f, 0x2f, 0x68, - 0xac, 0x09, 0x5b, 0x56, 0xd4, 0xb4, 0x15, 0x2c, 0xeb, 0xbf, 0x66, 0x01, 0x51, 0x87, 0x77, 0x3d, - 0xf4, 0xb1, 0x73, 0x2a, 0xba, 0xf1, 0x19, 0xcc, 0x30, 0xfd, 0xc7, 0xc0, 0xb4, 0x3b, 0xc4, 0x2e, - 0x62, 0x82, 0xaf, 0x16, 0x6d, 0x5d, 0xb2, 0xb5, 0xaa, 0x04, 0xd5, 0xc6, 0x41, 0xff, 0x54, 0xa0, - 0x66, 0x35, 0x54, 0xb5, 0x88, 0xa0, 0xaa, 0xdf, 0xe8, 0x1b, 0x98, 0xab, 0x79, 0xa7, 0x3d, 0xc2, - 0x13, 0x8e, 0x3c, 0xc6, 0xad, 0x0f, 0xde, 0xae, 0x56, 0xb8, 0x75, 0xc9, 0x8e, 0x55, 0x47, 0xbb, - 0x30, 0xff, 0xa0, 0xd3, 0x0f, 0x8e, 0x2b, 0xdd, 0x76, 0xad, 0xe3, 0x05, 0x82, 0xca, 0x38, 0x77, - 0x86, 0xf0, 0x65, 0x9b, 0xac, 0xb1, 0x75, 0xc9, 0x4e, 0x43, 0x44, 0xef, 0xf0, 0xdb, 0x7b, 0x6e, - 0x05, 0xcd, 0xde, 0xe5, 0x97, 0xfb, 0x4f, 0xba, 0xf8, 0xc9, 0xb3, 0xad, 0x4b, 0x36, 0x2b, 0xad, - 0xe6, 0x61, 0x4a, 0xa8, 0xac, 0x7b, 0x70, 0x45, 0x61, 0x27, 0xb1, 0xdb, 0xfa, 0x01, 0x2a, 0x41, - 0xee, 0xa0, 0xd7, 0xf1, 0x9c, 0xb6, 0x30, 0x03, 0x6c, 0xf9, 0x6d, 0xbd, 0xaf, 0x73, 0x1a, 0x2d, - 0xab, 0x67, 0x11, 0x56, 0x39, 0x02, 0x58, 0x5b, 0x3a, 0x73, 0x87, 0xd7, 0xd6, 0xda, 0xcd, 0xc6, - 0xda, 0x2d, 0xc4, 0x79, 0x6d, 0x2d, 0xa6, 0x32, 0xcf, 0x7a, 0x44, 0x4d, 0x9c, 0x4a, 0xaf, 0xd7, - 0x71, 0x5b, 0x74, 0x67, 0x60, 0x7a, 0x4d, 0x5a, 0x07, 0xbf, 0xa5, 0xde, 0x31, 0x2b, 0xdb, 0xa2, - 0xbc, 0x51, 0x56, 0x6e, 0x91, 0xad, 0x9f, 0xc1, 0x0d, 0x03, 0x31, 0xae, 0xe1, 0x3f, 0x83, 0x29, - 0x0e, 0x8a, 0x09, 0xb4, 0xea, 0x95, 0xa7, 0xeb, 0x29, 0xe0, 0x98, 0xa2, 0xbe, 0xf5, 0x1d, 0xac, - 0x1c, 0xf4, 0x02, 0xec, 0x27, 0xc9, 0x8b, 0xae, 0x7e, 0x2c, 0xef, 0xb0, 0x33, 0x46, 0x8f, 0x3f, - 0x9c, 0x0d, 0xca, 0x93, 0x8c, 0xb6, 0xb8, 0xba, 0xb6, 0x7e, 0x2f, 0x03, 0x2b, 0x6c, 0xa9, 0x1a, - 0x49, 0x5f, 0x84, 0x0b, 0x8a, 0x47, 0x39, 0x6b, 0xf6, 0x28, 0x0f, 0x75, 0xb1, 0x5b, 0xdf, 0x82, - 0xc5, 0x7b, 0xd4, 0xe9, 0xbc, 0xa1, 0xb9, 0xf9, 0x1b, 0x19, 0x58, 0x60, 0x93, 0xf3, 0x1a, 0x54, - 0xd0, 0x57, 0x30, 0x57, 0x3f, 0x71, 0x7b, 0x0d, 0xa7, 0xe3, 0xb6, 0x99, 0x73, 0x95, 0x6d, 0x24, - 0x8b, 0x74, 0x8f, 0x3c, 0x71, 0x7b, 0xcd, 0xe7, 0x51, 0x51, 0xc6, 0x8e, 0x55, 0xb6, 0x9e, 0xc0, - 0x62, 0xac, 0x0f, 0x5c, 0x30, 0x3e, 0x8e, 0x0b, 0x46, 0x22, 0x00, 0x21, 0x5d, 0x2a, 0x1e, 0xc3, - 0x55, 0x29, 0x15, 0xfa, 0x94, 0xad, 0xc5, 0xa4, 0x21, 0x41, 0x30, 0x4d, 0x14, 0x5a, 0x70, 0x55, - 0x4a, 0xc2, 0x6b, 0x48, 0x80, 0x98, 0xdc, 0x6c, 0xea, 0xe4, 0x6e, 0x43, 0x49, 0x9d, 0xdc, 0xd7, - 0x99, 0xd4, 0xff, 0x92, 0x81, 0xa5, 0x4d, 0xdc, 0xc5, 0xbe, 0x43, 0xbb, 0xac, 0x9d, 0x29, 0x54, - 0xc7, 0x72, 0x66, 0xa8, 0x63, 0x59, 0x1a, 0xcc, 0xd9, 0x74, 0x83, 0x99, 0xec, 0x86, 0x07, 0xf6, - 0x36, 0x97, 0x55, 0xba, 0x1b, 0xf6, 0x7d, 0xd7, 0x26, 0x30, 0xb4, 0x1d, 0x39, 0xa5, 0xc7, 0x47, - 0x3a, 0xa5, 0xe7, 0xb9, 0x93, 0x6e, 0x8a, 0x3b, 0xa5, 0x35, 0x57, 0xb4, 0xf5, 0x05, 0x14, 0x93, - 0x63, 0xe1, 0xf2, 0x31, 0xea, 0x90, 0x62, 0xad, 0x47, 0xd2, 0xcd, 0xef, 0xaf, 0xa5, 0x33, 0x3e, - 0xa6, 0x42, 0x87, 0x38, 0x7f, 0xac, 0x7a, 0x24, 0x9f, 0x9c, 0x0a, 0x6f, 0xff, 0x73, 0x22, 0x9f, - 0x2c, 0x46, 0x21, 0x63, 0x8e, 0x51, 0xe0, 0x32, 0xca, 0x50, 0x05, 0x82, 0xf5, 0x14, 0xae, 0x6a, - 0x44, 0x23, 0xa9, 0xff, 0x0a, 0x72, 0x02, 0x16, 0xf3, 0x4d, 0x68, 0x64, 0xe9, 0xbc, 0x05, 0x02, - 0x59, 0xa2, 0x58, 0x7f, 0x96, 0x81, 0x25, 0xb6, 0xbb, 0x24, 0xc7, 0x7d, 0xfe, 0xd9, 0xff, 0x8d, - 0x38, 0xbc, 0xee, 0xa7, 0x38, 0xbc, 0x28, 0x8a, 0xea, 0xf0, 0x52, 0xdd, 0x5c, 0x0f, 0xc7, 0x73, - 0xd9, 0xc2, 0x98, 0xd5, 0x80, 0x62, 0x72, 0x84, 0x6f, 0x60, 0x4e, 0x36, 0x61, 0x49, 0x59, 0xe8, - 0xaf, 0x2d, 0x31, 0x51, 0x8b, 0x6f, 0x50, 0x62, 0xa2, 0x8a, 0x6f, 0x4c, 0x62, 0xb6, 0x61, 0x9e, - 0x11, 0xd6, 0x57, 0xd7, 0xaa, 0xba, 0xba, 0x52, 0xe3, 0x65, 0x92, 0x0b, 0xee, 0x31, 0x5d, 0x70, - 0xa2, 0x4a, 0xd4, 0xc3, 0x8f, 0x60, 0x92, 0x87, 0x04, 0xb2, 0xfe, 0xa5, 0x10, 0xa3, 0x9a, 0x97, - 0xc5, 0x01, 0xda, 0xbc, 0xb2, 0x55, 0xa4, 0x43, 0x26, 0xe7, 0x14, 0xee, 0xf0, 0x96, 0xa7, 0xc6, - 0x6f, 0x89, 0x8a, 0x8b, 0x95, 0xbc, 0xe6, 0xae, 0xf1, 0x04, 0x8a, 0x6c, 0xd7, 0x50, 0xa8, 0xbe, - 0xd6, 0xbe, 0xf1, 0x29, 0x14, 0x99, 0x38, 0xa5, 0x10, 0x1c, 0xbe, 0x19, 0xac, 0xc0, 0xb2, 0xdc, - 0x0c, 0xd2, 0x46, 0xff, 0x77, 0x32, 0x70, 0x6d, 0x13, 0x87, 0x7a, 0xd4, 0xd4, 0x9f, 0xcb, 0xde, - 0xfd, 0x3d, 0x94, 0xd2, 0x3a, 0xc2, 0xa7, 0xe2, 0xeb, 0xf8, 0x54, 0x18, 0x43, 0xc4, 0xd2, 0xa7, - 0xe4, 0x67, 0x70, 0x9d, 0x4d, 0x89, 0x5e, 0x5f, 0x0c, 0xf4, 0x8b, 0xd8, 0xac, 0x18, 0xa9, 0xa7, - 0xcd, 0xce, 0xdf, 0xcf, 0xc0, 0x75, 0xc6, 0xe4, 0x74, 0xe2, 0xbf, 0x69, 0xeb, 0x6e, 0x17, 0xca, - 0x72, 0xce, 0xdf, 0xc0, 0xc4, 0x5a, 0x2d, 0x40, 0x82, 0x4c, 0xad, 0x6e, 0x0b, 0x12, 0xd7, 0x60, - 0xac, 0x56, 0xb7, 0xf9, 0x05, 0x34, 0xdd, 0xb4, 0x5b, 0x81, 0x6f, 0x13, 0x58, 0x5c, 0x83, 0x67, - 0xcf, 0xa1, 0xc1, 0xad, 0x9f, 0xc3, 0xbc, 0xd6, 0x08, 0x9f, 0xf7, 0x65, 0x18, 0xaf, 0x61, 0x3f, - 0xe4, 0xcd, 0xd0, 0x91, 0xb6, 0xb0, 0x1f, 0xda, 0x14, 0x8a, 0x6e, 0xc3, 0x54, 0xad, 0x42, 0xbd, - 0x8d, 0xd4, 0xb6, 0x98, 0x61, 0x8a, 0xa9, 0xe5, 0x34, 0x69, 0x24, 0xb9, 0x2d, 0x0a, 0xad, 0xff, - 0x90, 0x51, 0xa8, 0x13, 0xf4, 0xd1, 0x63, 0xf8, 0x80, 0x1c, 0x8f, 0x09, 0xcf, 0x94, 0x21, 0x5c, - 0x21, 0xdb, 0x16, 0xf7, 0xd4, 0xb0, 0x9d, 0xcf, 0x56, 0x2a, 0x9d, 0xd3, 0x53, 0x2a, 0x6e, 0xe6, - 0x18, 0x92, 0xf0, 0x22, 0xca, 0x9b, 0x39, 0x4e, 0x3a, 0xb0, 0xd5, 0x4a, 0xd6, 0xf7, 0xb0, 0xa0, - 0xf7, 0xff, 0x8d, 0xb2, 0xe7, 0x6d, 0x7a, 0xe5, 0xa3, 0x5c, 0x96, 0x22, 0xa4, 0x3a, 0x12, 0xb8, - 0x58, 0x7d, 0x02, 0x05, 0x5e, 0x2b, 0x5a, 0x96, 0xb7, 0x84, 0x69, 0xc7, 0x16, 0xa5, 0x1e, 0x5c, - 0x2c, 0xfc, 0xa1, 0x3f, 0x11, 0xae, 0x8a, 0x51, 0x2d, 0xfc, 0xa3, 0x0c, 0x14, 0x1f, 0x3f, 0xa8, - 0x54, 0xfa, 0xe1, 0x31, 0xee, 0x86, 0xe4, 0x50, 0x82, 0x6b, 0xc7, 0x4e, 0xa7, 0x83, 0xbb, 0x47, - 0x18, 0xdd, 0x81, 0xf1, 0xfd, 0x27, 0xfb, 0x7b, 0xdc, 0x23, 0xb0, 0xc0, 0x8f, 0xe3, 0x04, 0x24, - 0xeb, 0xd8, 0xb4, 0x06, 0x7a, 0x04, 0x57, 0x9e, 0xf2, 0x70, 0x7e, 0x59, 0xc4, 0x7d, 0x01, 0x37, - 0xee, 0xca, 0x40, 0xff, 0x9a, 0x8f, 0xdb, 0xa4, 0x15, 0xa7, 0x53, 0x09, 0x88, 0x62, 0x20, 0xf3, - 0x93, 0xc4, 0x7b, 0x38, 0x9e, 0xcb, 0x14, 0xb2, 0xd6, 0xef, 0x67, 0x60, 0x29, 0xd6, 0x33, 0xc5, - 0xb1, 0xab, 0x76, 0x6c, 0x5e, 0xe9, 0x98, 0xa8, 0xb2, 0x75, 0x89, 0xf7, 0xac, 0x46, 0x63, 0x47, - 0x69, 0x0b, 0xbc, 0x43, 0xef, 0x0c, 0xef, 0x50, 0x44, 0x40, 0x22, 0xf2, 0xc8, 0x2f, 0x0a, 0xb7, - 0x2e, 0xc3, 0xac, 0xc6, 0x01, 0xcb, 0x82, 0x19, 0xb5, 0x65, 0xc2, 0xe6, 0x9a, 0xd7, 0x96, 0x6c, - 0x26, 0x7f, 0x5b, 0xff, 0x20, 0x03, 0x0b, 0x8f, 0x1f, 0x54, 0x6c, 0x7c, 0xe4, 0x92, 0xe5, 0x17, - 0xb1, 0x78, 0x55, 0x1b, 0xc9, 0xb2, 0x36, 0x92, 0x58, 0x5d, 0x39, 0xa4, 0xcf, 0x13, 0x43, 0x5a, - 0x4e, 0x1b, 0x12, 0xb5, 0xb2, 0x5c, 0xaf, 0xab, 0x8d, 0x44, 0xf1, 0x7c, 0xfc, 0xe3, 0x0c, 0xcc, - 0x2b, 0x7d, 0x92, 0xfd, 0xff, 0x40, 0xeb, 0xd2, 0xf5, 0x94, 0x2e, 0x25, 0x98, 0x5c, 0x4d, 0xf4, - 0xe8, 0xed, 0x61, 0x3d, 0x1a, 0xc9, 0xe3, 0x3f, 0xce, 0xc0, 0x62, 0x2a, 0x0f, 0xd0, 0x55, 0xb2, - 0x6b, 0xb4, 0x7c, 0x1c, 0x72, 0xf6, 0xf2, 0x2f, 0x02, 0xdf, 0x0e, 0x82, 0x3e, 0x7f, 0x6b, 0x91, - 0xb7, 0xf9, 0x17, 0x7a, 0x1b, 0x66, 0xf7, 0xb0, 0xef, 0x7a, 0xed, 0x3a, 0x6e, 0x79, 0xdd, 0x36, - 0xf3, 0x08, 0xcf, 0xda, 0x3a, 0x10, 0x2d, 0x43, 0xbe, 0xd2, 0x39, 0xf2, 0x7c, 0x37, 0x3c, 0x66, - 0xce, 0xa7, 0xbc, 0x1d, 0x01, 0x08, 0xed, 0x75, 0xf7, 0xc8, 0x0d, 0xd9, 0xdd, 0xda, 0xac, 0xcd, - 0xbf, 0x50, 0x11, 0xa6, 0x2a, 0xad, 0x96, 0xd7, 0xef, 0x86, 0xd4, 0x03, 0x9a, 0xb7, 0xc5, 0x27, - 0xc1, 0xf8, 0xd6, 0xa6, 0x42, 0x40, 0xa3, 0xa1, 0x6c, 0xfe, 0x65, 0xbd, 0x07, 0x0b, 0x69, 0x7c, - 0x4c, 0x15, 0x99, 0xbf, 0x96, 0x85, 0xf9, 0x4a, 0xbb, 0xfd, 0xf8, 0x41, 0x65, 0x1d, 0xab, 0xc6, - 0xc7, 0x87, 0x30, 0xbe, 0xdd, 0x75, 0x43, 0xbe, 0x6b, 0xae, 0xf0, 0xe9, 0x49, 0xa9, 0x49, 0x6a, - 0x91, 0x19, 0x22, 0xff, 0x23, 0x1b, 0xe6, 0x37, 0x7e, 0x74, 0x83, 0xd0, 0xed, 0x1e, 0xd1, 0x39, - 0x67, 0x0d, 0xf3, 0x39, 0x16, 0x44, 0x0c, 0xcb, 0x6d, 0xeb, 0x92, 0x9d, 0x86, 0x8c, 0xf6, 0xe1, - 0xea, 0x2e, 0x7e, 0x91, 0x22, 0x42, 0x32, 0x98, 0x49, 0x92, 0x4d, 0x91, 0x1c, 0x03, 0xae, 0x2a, - 0xa1, 0x7f, 0x3b, 0x4b, 0x23, 0xe4, 0x94, 0x81, 0xf1, 0x96, 0x0f, 0x60, 0x41, 0xe9, 0x50, 0xa4, - 0x71, 0x32, 0x3c, 0x76, 0x3a, 0x75, 0x38, 0xea, 0x42, 0x4a, 0x45, 0x47, 0x4f, 0x61, 0x49, 0xef, - 0x54, 0x44, 0x59, 0x5f, 0x0c, 0x69, 0x55, 0xb6, 0x2e, 0xd9, 0x26, 0x6c, 0xb4, 0x0a, 0x63, 0x95, - 0xd6, 0x09, 0x67, 0x4b, 0xfa, 0x94, 0xb1, 0x91, 0x55, 0x5a, 0x27, 0x34, 0xda, 0xb4, 0x75, 0xa2, - 0xad, 0x87, 0xff, 0x98, 0x81, 0x25, 0xc3, 0x0c, 0xa3, 0x15, 0x00, 0x06, 0x54, 0x74, 0xbb, 0x02, - 0x21, 0xbb, 0x2a, 0xfb, 0xa2, 0x17, 0x8e, 0x63, 0xf4, 0xfe, 0x5a, 0xc4, 0x05, 0x45, 0x05, 0xb6, - 0x52, 0x09, 0xed, 0xc1, 0x34, 0xfb, 0x62, 0xe1, 0x49, 0xe3, 0x14, 0x07, 0x69, 0x38, 0x2c, 0x1e, - 0x89, 0xc6, 0x1c, 0xb4, 0x29, 0xa0, 0x19, 0x0f, 0x4b, 0x52, 0x49, 0xf0, 0xa3, 0x5f, 0x2d, 0x3e, - 0x0a, 0x39, 0x68, 0x74, 0x07, 0x26, 0x19, 0x90, 0xcf, 0xa1, 0x78, 0xf5, 0x12, 0x55, 0xe6, 0xe5, - 0xd6, 0x1f, 0x64, 0x84, 0x47, 0x27, 0xb1, 0x34, 0x3e, 0xd1, 0x96, 0xc6, 0x5b, 0xb2, 0xc3, 0x69, - 0x95, 0xb5, 0xd5, 0x51, 0x85, 0xe9, 0x57, 0x59, 0x15, 0x2a, 0x92, 0x2a, 0xb7, 0xff, 0x3c, 0x23, - 0xce, 0xa2, 0x49, 0xd1, 0xdd, 0x80, 0x99, 0x57, 0x13, 0x59, 0x0d, 0x0d, 0x7d, 0xc4, 0x24, 0x2a, - 0x3b, 0x7c, 0xa4, 0x43, 0x85, 0xea, 0x4b, 0xe1, 0xb4, 0x7a, 0x15, 0xb1, 0xb2, 0x96, 0x53, 0xb0, - 0x65, 0x73, 0x56, 0x3f, 0x51, 0x5a, 0x7f, 0xd9, 0x6d, 0x89, 0x79, 0xba, 0x1d, 0xbf, 0x64, 0x37, - 0xde, 0xa0, 0xaa, 0x7d, 0xc8, 0x46, 0x7e, 0x0c, 0x2e, 0x72, 0xd4, 0xa4, 0x55, 0x3b, 0x75, 0x16, - 0x5b, 0x27, 0xaf, 0xd2, 0x68, 0x0d, 0x66, 0x77, 0xf1, 0x8b, 0x44, 0xbb, 0xf4, 0x5e, 0xaa, 0x8b, - 0x5f, 0x34, 0x95, 0xb6, 0x15, 0x69, 0xd7, 0x71, 0xd0, 0x21, 0xcc, 0x09, 0x5d, 0x70, 0x5e, 0x95, - 0xc8, 0x22, 0x2e, 0x49, 0x0b, 0xa7, 0xcf, 0x9c, 0xa6, 0xcf, 0xa1, 0x6a, 0xa8, 0xa4, 0x4e, 0xd1, - 0xda, 0x83, 0x62, 0x72, 0xac, 0x5c, 0xca, 0x3e, 0x1c, 0xb5, 0x9c, 0xd8, 0xa9, 0xaa, 0xad, 0x2f, - 0xad, 0x2d, 0xea, 0x00, 0x90, 0x75, 0xe4, 0xd1, 0xe5, 0x7e, 0x9c, 0x75, 0x34, 0x8a, 0x4c, 0xb0, - 0x4e, 0x0d, 0xe9, 0x8e, 0xc2, 0x2c, 0x16, 0x63, 0x94, 0x78, 0xc7, 0xde, 0x83, 0x29, 0x0e, 0x92, - 0xa1, 0xf2, 0xf1, 0x85, 0x2e, 0x2a, 0x58, 0xff, 0x24, 0x03, 0xd7, 0x0e, 0x02, 0xec, 0xd7, 0xdd, - 0xee, 0x51, 0x07, 0x1f, 0x04, 0x7a, 0x90, 0xc3, 0x6f, 0x6b, 0x8b, 0x7d, 0xc9, 0x10, 0x3c, 0xf9, - 0xff, 0x6b, 0x89, 0xff, 0xb3, 0x0c, 0x94, 0xd2, 0xfa, 0xf6, 0x66, 0x57, 0xf9, 0x5d, 0x7e, 0xd6, - 0x60, 0xbd, 0x2d, 0x72, 0x74, 0xd9, 0xa6, 0x18, 0x2c, 0x19, 0x24, 0xf9, 0x5f, 0x5b, 0xde, 0xff, - 0x27, 0x03, 0x0b, 0xdb, 0x01, 0xed, 0xfe, 0x2f, 0xfa, 0xae, 0x8f, 0xdb, 0x82, 0x71, 0x77, 0xd3, - 0x42, 0x6c, 0xe9, 0xbc, 0x6e, 0x5d, 0x4a, 0x0b, 0xa1, 0xfd, 0x50, 0x09, 0x22, 0xcc, 0x0e, 0x8b, - 0x9d, 0xd5, 0xde, 0x6b, 0xdc, 0x86, 0xf1, 0x5d, 0x62, 0xd2, 0x8c, 0x71, 0xf9, 0x63, 0x18, 0x04, - 0x44, 0xe3, 0xfd, 0x48, 0x97, 0xc9, 0x07, 0x7a, 0x90, 0x88, 0x2a, 0x1c, 0x1f, 0x1d, 0x1b, 0x9a, - 0x7c, 0x68, 0x52, 0xcd, 0xc1, 0xe4, 0xbe, 0xe3, 0x1f, 0xe1, 0xd0, 0xfa, 0x19, 0x94, 0xf8, 0x65, - 0x1e, 0xf3, 0x91, 0xd1, 0x2b, 0xbf, 0x20, 0xf2, 0xdd, 0x0c, 0xbb, 0x80, 0x5b, 0x01, 0xa8, 0x87, - 0x8e, 0x1f, 0x6e, 0x77, 0xdb, 0xf8, 0x47, 0x3a, 0xda, 0x09, 0x5b, 0x81, 0x58, 0x1f, 0x41, 0x5e, - 0x0e, 0x81, 0x9e, 0xa7, 0x14, 0xab, 0x8d, 0x0e, 0x67, 0x41, 0x8b, 0x73, 0x14, 0xc1, 0x8d, 0x6b, - 0xb0, 0x18, 0x9b, 0x0a, 0x2e, 0x27, 0x25, 0x32, 0x61, 0x0c, 0xc6, 0x2e, 0xfa, 0x6d, 0xf9, 0x6d, - 0xd5, 0xe0, 0x4a, 0x62, 0xa6, 0x11, 0xa2, 0xb1, 0xab, 0xec, 0xf0, 0x49, 0x94, 0x7a, 0xbd, 0xbe, - 0x45, 0x60, 0xfb, 0x3b, 0x75, 0x16, 0xc7, 0x43, 0x60, 0xfb, 0x3b, 0xf5, 0xea, 0x24, 0x93, 0x1c, - 0xeb, 0x5f, 0x67, 0xe9, 0x11, 0x32, 0xc1, 0x83, 0x98, 0x2b, 0x42, 0x75, 0x87, 0x54, 0x21, 0x4f, - 0x47, 0xbc, 0x2e, 0xe2, 0xdd, 0x86, 0xdf, 0x00, 0xe4, 0x7e, 0x39, 0x28, 0x5f, 0xa2, 0x6e, 0xff, - 0x08, 0x0d, 0x7d, 0x0d, 0x53, 0x1b, 0xdd, 0x36, 0xa5, 0x30, 0x76, 0x01, 0x0a, 0x02, 0x89, 0xcc, - 0x03, 0xed, 0x32, 0x31, 0x47, 0xf8, 0x79, 0xdd, 0x56, 0x20, 0x94, 0xcd, 0xee, 0xa9, 0xcb, 0xee, - 0x79, 0x27, 0x6c, 0xf6, 0x41, 0xb8, 0x49, 0xbb, 0x20, 0x9e, 0x2f, 0xe4, 0x6d, 0xf9, 0x8d, 0x2c, - 0x98, 0x78, 0xe2, 0xb7, 0x79, 0x30, 0xf9, 0xdc, 0xea, 0x8c, 0x78, 0xcf, 0x4d, 0x60, 0x36, 0x2b, - 0xb2, 0xfe, 0x17, 0xbd, 0x7b, 0x09, 0x53, 0xe5, 0x46, 0xe3, 0x4a, 0xe6, 0xb5, 0xb9, 0x92, 0x7d, - 0x15, 0xae, 0xc8, 0x51, 0x8f, 0x99, 0x46, 0x3d, 0x6e, 0x1a, 0xf5, 0x84, 0x79, 0xd4, 0x9b, 0x30, - 0xc9, 0x86, 0x8a, 0x6e, 0xc1, 0xc4, 0x76, 0x88, 0x4f, 0x23, 0xd7, 0x82, 0x7a, 0x7b, 0x6e, 0xb3, - 0x32, 0x72, 0xea, 0xd9, 0x71, 0x82, 0x50, 0x44, 0x8e, 0xe5, 0x6d, 0xf1, 0x69, 0xfd, 0x49, 0x06, - 0x0a, 0x3b, 0x6e, 0x10, 0x92, 0x85, 0x70, 0x4e, 0x59, 0x93, 0x23, 0xca, 0x9a, 0x46, 0x34, 0x16, - 0x1b, 0xd1, 0x17, 0x30, 0x49, 0x03, 0x1a, 0x03, 0xfe, 0x54, 0xe9, 0x16, 0x1f, 0x52, 0xbc, 0x61, - 0x16, 0xf6, 0x18, 0xd0, 0x27, 0x45, 0x36, 0x47, 0x29, 0x7d, 0x06, 0xd3, 0x0a, 0xf8, 0x42, 0x2f, - 0x8d, 0xbe, 0x83, 0x2b, 0x4a, 0x13, 0xd2, 0x0f, 0x31, 0xc2, 0x5b, 0x2d, 0xbd, 0xa1, 0x84, 0x6d, - 0xbb, 0xf8, 0x47, 0x95, 0x6d, 0xfc, 0xd3, 0xfa, 0x81, 0xc6, 0xe3, 0xee, 0x78, 0xad, 0x13, 0xc5, - 0x57, 0x38, 0xc5, 0x94, 0x59, 0xdc, 0xe5, 0x4e, 0x6a, 0xb1, 0x12, 0x5b, 0xd4, 0x40, 0x37, 0x61, - 0x7a, 0xbb, 0xfb, 0xc0, 0xf3, 0x5b, 0xf8, 0x49, 0xb7, 0xc3, 0xa8, 0xe7, 0x6c, 0x15, 0xc4, 0xdd, - 0x48, 0xbc, 0x85, 0xc8, 0x8d, 0x44, 0x01, 0x31, 0x37, 0x12, 0x7b, 0x29, 0x69, 0xb3, 0x32, 0xee, - 0xa5, 0x22, 0x7f, 0x0f, 0xf3, 0x21, 0x49, 0x67, 0xd3, 0xa8, 0x8a, 0x87, 0x70, 0xcd, 0xc6, 0xbd, - 0x8e, 0x43, 0x6c, 0xc5, 0x53, 0x8f, 0xd5, 0x97, 0x63, 0xbe, 0x99, 0x12, 0x2a, 0xa6, 0xdf, 0x38, - 0xc9, 0x2e, 0x67, 0x87, 0x74, 0xf9, 0x14, 0xde, 0xda, 0xc4, 0x61, 0xea, 0x73, 0xc7, 0x68, 0xf0, - 0x5b, 0x90, 0xe3, 0x21, 0xf9, 0x62, 0xfc, 0xa3, 0x5e, 0x5a, 0xf2, 0xeb, 0x17, 0x4e, 0x47, 0xfe, - 0x65, 0x7d, 0x03, 0x65, 0x53, 0x73, 0xe7, 0x8b, 0x10, 0x72, 0xe1, 0xa6, 0x99, 0x80, 0xb4, 0x26, - 0xa6, 0x78, 0x83, 0xf2, 0xd4, 0x3f, 0xbc, 0xb7, 0xd2, 0x21, 0x4f, 0xed, 0x29, 0xfe, 0x87, 0x55, - 0x15, 0x21, 0x08, 0xaf, 0xd1, 0xdd, 0x26, 0xbd, 0x32, 0xd0, 0x09, 0x44, 0x7c, 0xad, 0x40, 0x4e, - 0xc0, 0x62, 0x77, 0x06, 0x89, 0x97, 0xa4, 0x94, 0xa1, 0x6d, 0x41, 0x40, 0xa2, 0x59, 0x3f, 0x08, - 0xc7, 0xbe, 0x8e, 0x71, 0xbe, 0xb0, 0xd3, 0xf3, 0x78, 0xf2, 0x2d, 0x0f, 0xae, 0xe9, 0xb4, 0x55, - 0xf7, 0x74, 0x41, 0x71, 0x4f, 0x33, 0xaf, 0x34, 0x91, 0x4b, 0x7b, 0x67, 0xa3, 0xdb, 0xee, 0x79, - 0x6e, 0x37, 0xe4, 0x8b, 0x57, 0x05, 0xa1, 0x15, 0xd5, 0x09, 0x3d, 0x93, 0x8c, 0xd3, 0xbd, 0x0f, - 0xa5, 0xb4, 0x06, 0x15, 0xdf, 0x8f, 0xf4, 0x27, 0x33, 0x3b, 0xce, 0x3a, 0x86, 0x05, 0x2d, 0x37, - 0x47, 0x94, 0x6c, 0x20, 0xca, 0x49, 0x92, 0xaf, 0x7e, 0xf9, 0xeb, 0x41, 0xf9, 0xd3, 0x8b, 0x04, - 0x83, 0x0a, 0x9a, 0xfb, 0x32, 0xd4, 0xd8, 0x5a, 0x82, 0xb1, 0x9a, 0xbd, 0x43, 0x87, 0x6d, 0xef, - 0xc8, 0x61, 0xdb, 0x3b, 0xd6, 0xaf, 0x33, 0x50, 0xae, 0x1d, 0x3b, 0xdd, 0x23, 0x6a, 0x7b, 0x28, - 0xe6, 0xaa, 0x72, 0xaf, 0x7a, 0xde, 0x23, 0xd5, 0x2a, 0x4c, 0xef, 0xe2, 0x17, 0x22, 0x4c, 0x9a, - 0x07, 0x1c, 0x53, 0xf7, 0x3b, 0x39, 0xee, 0xf4, 0x38, 0xdc, 0x56, 0x2b, 0xa1, 0xbf, 0xfc, 0xea, - 0xce, 0x25, 0xf6, 0x42, 0x3f, 0x3a, 0x49, 0xb1, 0xd2, 0xb4, 0x23, 0x95, 0xa1, 0x09, 0xeb, 0xdf, - 0x66, 0xe0, 0xa6, 0x79, 0xf0, 0x7c, 0xe2, 0xd6, 0xb5, 0x3c, 0x07, 0x43, 0x6e, 0x84, 0xe9, 0x91, - 0x55, 0xc9, 0x73, 0x10, 0xcf, 0x6d, 0x60, 0xe3, 0x96, 0xf7, 0x1c, 0xfb, 0x2f, 0x63, 0x7e, 0x76, - 0x01, 0xae, 0x91, 0x2d, 0x47, 0x64, 0x89, 0x61, 0x20, 0xed, 0x69, 0x23, 0x87, 0x59, 0xff, 0x39, - 0x03, 0xd7, 0xe9, 0x36, 0xc9, 0xbd, 0x90, 0xa2, 0xe0, 0xe2, 0xf1, 0x03, 0x1f, 0xc1, 0x8c, 0xda, - 0x38, 0x9f, 0x30, 0xfa, 0x30, 0x5a, 0xf4, 0xa0, 0xd9, 0xf2, 0xda, 0xd8, 0xd6, 0xaa, 0xa1, 0x6d, - 0x98, 0xe6, 0xdf, 0x8a, 0xab, 0x69, 0x51, 0xc9, 0x9a, 0x42, 0xe5, 0x81, 0x79, 0x8e, 0xe8, 0xec, - 0x73, 0x62, 0x4d, 0x1a, 0xfa, 0xae, 0xe2, 0x5a, 0xbf, 0xca, 0xc2, 0x72, 0x03, 0xfb, 0xee, 0xb3, - 0x97, 0x86, 0xc1, 0x3c, 0x81, 0x05, 0x01, 0xa2, 0x63, 0xd6, 0xe5, 0x90, 0x3d, 0x51, 0x13, 0x5d, - 0x0d, 0x48, 0x85, 0xa6, 0x14, 0xcb, 0x54, 0xc4, 0x0b, 0x3c, 0xda, 0xfc, 0x10, 0x72, 0x52, 0x94, - 0xc7, 0x28, 0x67, 0xe8, 0xdc, 0x08, 0x31, 0xd6, 0xdf, 0xaf, 0x4b, 0x79, 0xfe, 0x9b, 0xe6, 0xeb, - 0x0c, 0x7e, 0xe2, 0x19, 0x71, 0x18, 0x65, 0x52, 0x4d, 0x24, 0xda, 0x51, 0x4a, 0x53, 0xa4, 0x7a, - 0xeb, 0x92, 0x6d, 0x6a, 0xa9, 0x3a, 0x0d, 0xf9, 0x0a, 0xbd, 0x6c, 0x21, 0x07, 0x8c, 0xff, 0x9d, - 0x85, 0x15, 0x11, 0x52, 0x68, 0x60, 0xf3, 0x77, 0xb0, 0x24, 0x40, 0x95, 0x5e, 0xcf, 0xf7, 0x9e, - 0xe3, 0xb6, 0xce, 0x69, 0xf6, 0x4c, 0x54, 0x70, 0xda, 0xe1, 0x75, 0x22, 0x66, 0x9b, 0xd0, 0xdf, - 0x8c, 0x9b, 0xe5, 0x6b, 0x5d, 0xb1, 0xb0, 0xd9, 0xa0, 0x4e, 0x49, 0x55, 0xb1, 0xe8, 0x09, 0x7e, - 0x54, 0x25, 0xd3, 0x4e, 0xb8, 0x69, 0xc6, 0x5f, 0xd7, 0x4d, 0x43, 0x8e, 0xa6, 0x3a, 0xcd, 0xea, - 0x1c, 0xcc, 0xec, 0xe2, 0x17, 0x11, 0xdf, 0x7f, 0x37, 0x03, 0xb3, 0xda, 0xe2, 0x46, 0xef, 0xc2, - 0x04, 0xfd, 0x83, 0x6e, 0x9a, 0xfc, 0xad, 0x0c, 0x59, 0x60, 0xda, 0x5b, 0x19, 0x56, 0x75, 0x1b, - 0xa6, 0x58, 0xf8, 0x4c, 0xfb, 0x1c, 0x67, 0x08, 0x19, 0x9d, 0xd5, 0x62, 0x28, 0xec, 0x38, 0xc1, - 0xf1, 0xad, 0x47, 0xf0, 0x16, 0x8f, 0xc4, 0xd1, 0x27, 0xbf, 0xa6, 0xda, 0xef, 0xe7, 0xd4, 0xf1, - 0x96, 0x03, 0x2b, 0x9b, 0x38, 0xae, 0x7a, 0xb4, 0xe8, 0xb5, 0x6f, 0xe0, 0xb2, 0x06, 0x97, 0x14, - 0x69, 0x3c, 0xbd, 0x94, 0x21, 0x49, 0x3a, 0x5e, 0xdb, 0xba, 0x99, 0xd6, 0x84, 0xda, 0x59, 0x0b, - 0xc3, 0x65, 0x7a, 0x52, 0x96, 0x37, 0x4e, 0xc1, 0x05, 0xb4, 0xde, 0x1d, 0x65, 0x5d, 0x33, 0x8d, - 0xc7, 0x9e, 0x62, 0x8a, 0xed, 0x49, 0x96, 0x5a, 0xb3, 0x30, 0x5d, 0xf3, 0xba, 0x21, 0xfe, 0x91, - 0x3e, 0x86, 0xb0, 0xe6, 0x60, 0x46, 0x14, 0x75, 0x70, 0x10, 0x58, 0xff, 0x74, 0x0c, 0x2c, 0xce, - 0xd8, 0x34, 0x2f, 0x8f, 0xe0, 0xc7, 0x61, 0xa2, 0xb3, 0x7c, 0x13, 0xb9, 0xaa, 0xfa, 0xb2, 0xa2, - 0x52, 0x26, 0x79, 0xf4, 0xf1, 0x4a, 0x2b, 0x82, 0x6a, 0x92, 0x97, 0x18, 0xfd, 0xcf, 0x0d, 0x6a, - 0x92, 0x2d, 0x36, 0x9a, 0x3e, 0xc4, 0xa0, 0x26, 0x35, 0xba, 0xe9, 0x2a, 0xd3, 0xd6, 0xd8, 0xc0, - 0xf7, 0x65, 0x24, 0x43, 0xbf, 0x65, 0x09, 0x4f, 0xb9, 0xc5, 0x00, 0xcd, 0x44, 0xca, 0x2c, 0x95, - 0x08, 0x3a, 0xd0, 0x79, 0xc9, 0xd7, 0xa3, 0xb8, 0xe1, 0x55, 0x8b, 0x18, 0xd5, 0x9e, 0x02, 0xd1, - 0x33, 0x90, 0x69, 0x75, 0x15, 0xcf, 0xdd, 0x3f, 0xcc, 0xc0, 0x75, 0x36, 0x3b, 0x7b, 0xbe, 0xfb, - 0xdc, 0xed, 0xe0, 0x23, 0xac, 0x89, 0x69, 0x3f, 0xfd, 0xa6, 0x2c, 0x73, 0x2e, 0x1d, 0x4d, 0x93, - 0x36, 0x60, 0x8e, 0x6e, 0x72, 0xe4, 0xa6, 0xd1, 0xb7, 0x06, 0x19, 0x58, 0x11, 0x6f, 0xca, 0x62, - 0xd7, 0x47, 0x17, 0x35, 0xb7, 0xaa, 0xda, 0x8d, 0x4f, 0xd6, 0x70, 0xe3, 0xa3, 0x79, 0xd2, 0xc3, - 0x11, 0x57, 0x40, 0x63, 0xaf, 0x7d, 0x05, 0x64, 0xfd, 0x61, 0x16, 0xae, 0xec, 0x39, 0x47, 0x6e, + 0x4d, 0x8b, 0x2e, 0x44, 0xe4, 0x77, 0x33, 0x50, 0xae, 0xf9, 0x98, 0xcc, 0xb4, 0x91, 0xd0, 0xf0, + 0x15, 0xbc, 0xcc, 0x2f, 0x17, 0xb2, 0x51, 0x29, 0xe1, 0x35, 0xbf, 0x40, 0x78, 0x07, 0xc6, 0xf6, + 0xf7, 0x77, 0xa8, 0xc4, 0x8c, 0x51, 0xc6, 0x8d, 0x85, 0x61, 0xe7, 0xd7, 0x83, 0x72, 0x6e, 0xbd, + 0xcf, 0x2e, 0x1f, 0x6c, 0x52, 0x6e, 0x3d, 0x83, 0x45, 0x1b, 0x77, 0xf1, 0x0b, 0xe7, 0xb0, 0x83, + 0x35, 0x73, 0xb5, 0x0c, 0x13, 0xcc, 0x59, 0x96, 0x18, 0x02, 0x83, 0xeb, 0xf6, 0x6c, 0x76, 0x84, + 0x3d, 0x6b, 0xfd, 0x61, 0x06, 0x0a, 0x6c, 0xb8, 0x55, 0x2f, 0x3c, 0xdf, 0xf8, 0xf8, 0x08, 0xb2, + 0xc3, 0x47, 0x80, 0x6e, 0x47, 0xdc, 0x1e, 0x8b, 0x36, 0x3f, 0xda, 0x55, 0xa2, 0xc3, 0x45, 0x21, + 0x19, 0x10, 0x93, 0x25, 0x76, 0x34, 0xa2, 0x03, 0xa2, 0xb2, 0x24, 0x24, 0xe8, 0x8f, 0xb3, 0x70, + 0x45, 0xe9, 0x62, 0xd0, 0xf3, 0xba, 0x01, 0x26, 0x67, 0x3c, 0x22, 0x2c, 0x4a, 0x3f, 0xe9, 0x19, + 0x8f, 0x6c, 0x99, 0xcd, 0xc8, 0x12, 0xa7, 0x1d, 0x7e, 0x97, 0x1c, 0x2e, 0x3a, 0x89, 0xe3, 0x20, + 0x55, 0xdc, 0xac, 0xaa, 0x28, 0x3e, 0x77, 0xa7, 0xef, 0x41, 0x8e, 0xfe, 0x49, 0x18, 0x31, 0x6e, + 0x66, 0x84, 0xac, 0x84, 0x5c, 0x80, 0x87, 0x9e, 0xdb, 0x7d, 0x8c, 0xc3, 0x63, 0x4f, 0x1c, 0x9e, + 0xb7, 0x89, 0x12, 0xfb, 0x2b, 0x9e, 0xdb, 0x6d, 0x9e, 0x52, 0xf0, 0x45, 0x0f, 0x9d, 0x11, 0x41, + 0x5b, 0x21, 0x6e, 0xdd, 0x87, 0x02, 0xd1, 0x37, 0xe7, 0x9f, 0x51, 0x6b, 0x01, 0xd0, 0x26, 0x0e, + 0xab, 0x9e, 0xb6, 0x71, 0x58, 0xb3, 0x30, 0xbd, 0xe7, 0x76, 0x8f, 0xc4, 0xe7, 0xbf, 0xcf, 0xc2, + 0x0c, 0xfb, 0xe6, 0x33, 0x10, 0xdb, 0x49, 0x33, 0xe7, 0xd9, 0x49, 0x3f, 0x85, 0x59, 0xee, 0xce, + 0xc1, 0x3e, 0x75, 0x21, 0xb3, 0xf9, 0xa0, 0x27, 0x4a, 0xe6, 0xd5, 0x69, 0x3e, 0x67, 0x25, 0xb6, + 0x5e, 0x11, 0xed, 0xc0, 0x1c, 0x03, 0x3c, 0xc0, 0x4e, 0xd8, 0x8f, 0x4e, 0x55, 0x97, 0xb9, 0x9d, + 0x29, 0xc0, 0x4c, 0x19, 0x71, 0x5a, 0xcf, 0x38, 0xd0, 0x8e, 0xe1, 0xa2, 0x6f, 0xe0, 0xf2, 0x9e, + 0xef, 0xfd, 0xf8, 0x52, 0xb1, 0x1d, 0x98, 0x3e, 0x5e, 0x24, 0x87, 0xb0, 0x1e, 0x29, 0x6a, 0xaa, + 0x16, 0x44, 0xbc, 0x36, 0x91, 0xa9, 0xed, 0xa0, 0xea, 0xf9, 0x6e, 0xf7, 0x88, 0xce, 0x66, 0x8e, + 0xc9, 0x94, 0x1b, 0x34, 0x0f, 0x29, 0xd0, 0x96, 0xc5, 0xd6, 0x1f, 0x8d, 0x41, 0x4e, 0x36, 0x7c, + 0x57, 0x35, 0x4b, 0xf9, 0x66, 0x4c, 0x97, 0x67, 0x74, 0xf8, 0xb1, 0x95, 0x1a, 0xe8, 0x1a, 0x73, + 0x66, 0x31, 0x33, 0x60, 0x8a, 0xc8, 0x98, 0xd3, 0xeb, 0x51, 0x97, 0x15, 0x51, 0xa6, 0xeb, 0x55, + 0xca, 0x85, 0x1c, 0x53, 0xa6, 0xed, 0x43, 0x3b, 0xbb, 0x5e, 0x25, 0x73, 0xfd, 0x64, 0x7b, 0xbd, + 0x46, 0x07, 0x94, 0x63, 0x73, 0xed, 0xb9, 0xed, 0x96, 0x4d, 0xa1, 0xa4, 0xb4, 0x5e, 0x79, 0xbc, + 0xc3, 0x3b, 0x4d, 0x4b, 0x03, 0xe7, 0xb4, 0x63, 0x53, 0x28, 0xb1, 0x03, 0xd9, 0x1e, 0x5d, 0xf3, + 0xba, 0xa1, 0xef, 0x75, 0x02, 0xea, 0x2a, 0xc8, 0x69, 0xdb, 0x79, 0x8b, 0x17, 0xd9, 0xb1, 0xaa, + 0xe8, 0x29, 0x2c, 0x55, 0xda, 0xcf, 0x9d, 0x6e, 0x0b, 0xb7, 0x59, 0xc9, 0x53, 0xcf, 0x3f, 0x79, + 0xd6, 0xf1, 0x5e, 0x04, 0xf4, 0x94, 0x97, 0xe3, 0xe7, 0x45, 0x5e, 0xa5, 0xc9, 0xc9, 0xbd, 0x10, + 0x95, 0x6c, 0x13, 0x36, 0x51, 0x11, 0xb5, 0x8e, 0xd7, 0x6f, 0xd3, 0xe3, 0x5d, 0x8e, 0xa9, 0x88, + 0x16, 0x01, 0xd8, 0x0c, 0x4e, 0xb8, 0xb4, 0x55, 0x7f, 0x4c, 0x4f, 0x67, 0x9c, 0x4b, 0xc7, 0xc1, + 0xa9, 0x4d, 0x60, 0xe8, 0x1d, 0x98, 0x12, 0x26, 0x2d, 0x73, 0x0a, 0x50, 0x8f, 0x91, 0x30, 0x65, + 0x45, 0x99, 0xf5, 0x01, 0x5c, 0x61, 0x8b, 0xe6, 0xdc, 0x96, 0x9a, 0xb5, 0x07, 0x50, 0xc7, 0xa7, + 0x4e, 0xef, 0xd8, 0x23, 0x13, 0x5b, 0x55, 0xbf, 0xb8, 0xe9, 0x82, 0xa4, 0xa3, 0x9f, 0x17, 0x34, + 0xd6, 0x84, 0x2d, 0x2b, 0x6a, 0xda, 0x0a, 0x96, 0xf5, 0x5f, 0xb3, 0x80, 0xa8, 0xc3, 0xbb, 0x1e, + 0xfa, 0xd8, 0x39, 0x15, 0xdd, 0xf8, 0x0c, 0x66, 0x98, 0xfe, 0x63, 0x60, 0xda, 0x1d, 0x62, 0x17, + 0x31, 0xc1, 0x57, 0x8b, 0xb6, 0x2e, 0xd9, 0x5a, 0x55, 0x82, 0x6a, 0xe3, 0xa0, 0x7f, 0x2a, 0x50, + 0xb3, 0x1a, 0xaa, 0x5a, 0x44, 0x50, 0xd5, 0x6f, 0xf4, 0x0d, 0xcc, 0xd5, 0xbc, 0xd3, 0x1e, 0xe1, + 0x09, 0x47, 0x1e, 0xe3, 0xd6, 0x07, 0x6f, 0x57, 0x2b, 0xdc, 0xba, 0x64, 0xc7, 0xaa, 0xa3, 0x5d, + 0x98, 0x7f, 0xd0, 0xe9, 0x07, 0xc7, 0x95, 0x6e, 0xbb, 0xd6, 0xf1, 0x02, 0x41, 0x65, 0x9c, 0x3b, + 0x43, 0xf8, 0xb2, 0x4d, 0xd6, 0xd8, 0xba, 0x64, 0xa7, 0x21, 0xa2, 0x77, 0xf8, 0xed, 0x3d, 0xb7, + 0x82, 0x66, 0xef, 0xf2, 0xcb, 0xfd, 0x27, 0x5d, 0xfc, 0xe4, 0xd9, 0xd6, 0x25, 0x9b, 0x95, 0x56, + 0xf3, 0x30, 0x25, 0x54, 0xd6, 0x3d, 0xb8, 0xa2, 0xb0, 0x93, 0xd8, 0x6d, 0xfd, 0x00, 0x95, 0x20, + 0x77, 0xd0, 0xeb, 0x78, 0x4e, 0x5b, 0x98, 0x01, 0xb6, 0xfc, 0xb6, 0xde, 0xd7, 0x39, 0x8d, 0x96, + 0xd5, 0xb3, 0x08, 0xab, 0x1c, 0x01, 0xac, 0x2d, 0x9d, 0xb9, 0xc3, 0x6b, 0x6b, 0xed, 0x66, 0x63, + 0xed, 0x16, 0xe2, 0xbc, 0xb6, 0x16, 0x53, 0x99, 0x67, 0x3d, 0xa2, 0x26, 0x4e, 0xa5, 0xd7, 0xeb, + 0xb8, 0x2d, 0xba, 0x33, 0x30, 0xbd, 0x26, 0xad, 0x83, 0xdf, 0x52, 0xef, 0x98, 0x95, 0x6d, 0x51, + 0xde, 0x28, 0x2b, 0xb7, 0xc8, 0xd6, 0xcf, 0xe0, 0x86, 0x81, 0x18, 0xd7, 0xf0, 0x9f, 0xc1, 0x14, + 0x07, 0xc5, 0x04, 0x5a, 0xf5, 0xca, 0xd3, 0xf5, 0x14, 0x70, 0x4c, 0x51, 0xdf, 0xfa, 0x0e, 0x56, + 0x0e, 0x7a, 0x01, 0xf6, 0x93, 0xe4, 0x45, 0x57, 0x3f, 0x96, 0x77, 0xd8, 0x19, 0xa3, 0xc7, 0x1f, + 0xce, 0x06, 0xe5, 0x49, 0x46, 0x5b, 0x5c, 0x5d, 0x5b, 0xbf, 0x9f, 0x81, 0x15, 0xb6, 0x54, 0x8d, + 0xa4, 0x2f, 0xc2, 0x05, 0xc5, 0xa3, 0x9c, 0x35, 0x7b, 0x94, 0x87, 0xba, 0xd8, 0xad, 0x6f, 0xc1, + 0xe2, 0x3d, 0xea, 0x74, 0xde, 0xd0, 0xdc, 0xfc, 0xad, 0x0c, 0x2c, 0xb0, 0xc9, 0x79, 0x0d, 0x2a, + 0xe8, 0x2b, 0x98, 0xab, 0x9f, 0xb8, 0xbd, 0x86, 0xd3, 0x71, 0xdb, 0xcc, 0xb9, 0xca, 0x36, 0x92, + 0x45, 0xba, 0x47, 0x9e, 0xb8, 0xbd, 0xe6, 0xf3, 0xa8, 0x28, 0x63, 0xc7, 0x2a, 0x5b, 0x4f, 0x60, + 0x31, 0xd6, 0x07, 0x2e, 0x18, 0x1f, 0xc7, 0x05, 0x23, 0x11, 0x80, 0x90, 0x2e, 0x15, 0x8f, 0xe1, + 0xaa, 0x94, 0x0a, 0x7d, 0xca, 0xd6, 0x62, 0xd2, 0x90, 0x20, 0x98, 0x26, 0x0a, 0x2d, 0xb8, 0x2a, + 0x25, 0xe1, 0x35, 0x24, 0x40, 0x4c, 0x6e, 0x36, 0x75, 0x72, 0xb7, 0xa1, 0xa4, 0x4e, 0xee, 0xeb, + 0x4c, 0xea, 0x7f, 0xc9, 0xc0, 0xd2, 0x26, 0xee, 0x62, 0xdf, 0xa1, 0x5d, 0xd6, 0xce, 0x14, 0xaa, + 0x63, 0x39, 0x33, 0xd4, 0xb1, 0x2c, 0x0d, 0xe6, 0x6c, 0xba, 0xc1, 0x4c, 0x76, 0xc3, 0x03, 0x7b, + 0x9b, 0xcb, 0x2a, 0xdd, 0x0d, 0xfb, 0xbe, 0x6b, 0x13, 0x18, 0xda, 0x8e, 0x9c, 0xd2, 0xe3, 0x23, + 0x9d, 0xd2, 0xf3, 0xdc, 0x49, 0x37, 0xc5, 0x9d, 0xd2, 0x9a, 0x2b, 0xda, 0xfa, 0x02, 0x8a, 0xc9, + 0xb1, 0x70, 0xf9, 0x18, 0x75, 0x48, 0xb1, 0xd6, 0x23, 0xe9, 0xe6, 0xf7, 0xd7, 0xd2, 0x19, 0x1f, + 0x53, 0xa1, 0x43, 0x9c, 0x3f, 0x56, 0x3d, 0x92, 0x4f, 0x4e, 0x85, 0xb7, 0xff, 0x39, 0x91, 0x4f, + 0x16, 0xa3, 0x90, 0x31, 0xc7, 0x28, 0x70, 0x19, 0x65, 0xa8, 0x02, 0xc1, 0x7a, 0x0a, 0x57, 0x35, + 0xa2, 0x91, 0xd4, 0x7f, 0x05, 0x39, 0x01, 0x8b, 0xf9, 0x26, 0x34, 0xb2, 0x74, 0xde, 0x02, 0x81, + 0x2c, 0x51, 0xac, 0x3f, 0xcf, 0xc0, 0x12, 0xdb, 0x5d, 0x92, 0xe3, 0x3e, 0xff, 0xec, 0xff, 0x46, + 0x1c, 0x5e, 0xf7, 0x53, 0x1c, 0x5e, 0x14, 0x45, 0x75, 0x78, 0xa9, 0x6e, 0xae, 0x87, 0xe3, 0xb9, + 0x6c, 0x61, 0xcc, 0x6a, 0x40, 0x31, 0x39, 0xc2, 0x37, 0x30, 0x27, 0x9b, 0xb0, 0xa4, 0x2c, 0xf4, + 0xd7, 0x96, 0x98, 0xa8, 0xc5, 0x37, 0x28, 0x31, 0x51, 0xc5, 0x37, 0x26, 0x31, 0xdb, 0x30, 0xcf, + 0x08, 0xeb, 0xab, 0x6b, 0x55, 0x5d, 0x5d, 0xa9, 0xf1, 0x32, 0xc9, 0x05, 0xf7, 0x98, 0x2e, 0x38, + 0x51, 0x25, 0xea, 0xe1, 0x47, 0x30, 0xc9, 0x43, 0x02, 0x59, 0xff, 0x52, 0x88, 0x51, 0xcd, 0xcb, + 0xe2, 0x00, 0x6d, 0x5e, 0xd9, 0x2a, 0xd2, 0x21, 0x93, 0x73, 0x0a, 0x77, 0x78, 0xcb, 0x53, 0xe3, + 0xb7, 0x44, 0xc5, 0xc5, 0x4a, 0x5e, 0x73, 0xd7, 0x78, 0x02, 0x45, 0xb6, 0x6b, 0x28, 0x54, 0x5f, + 0x6b, 0xdf, 0xf8, 0x14, 0x8a, 0x4c, 0x9c, 0x52, 0x08, 0x0e, 0xdf, 0x0c, 0x56, 0x60, 0x59, 0x6e, + 0x06, 0x69, 0xa3, 0xff, 0xbb, 0x19, 0xb8, 0xb6, 0x89, 0x43, 0x3d, 0x6a, 0xea, 0x2f, 0x64, 0xef, + 0xfe, 0x1e, 0x4a, 0x69, 0x1d, 0xe1, 0x53, 0xf1, 0x75, 0x7c, 0x2a, 0x8c, 0x21, 0x62, 0xe9, 0x53, + 0xf2, 0x33, 0xb8, 0xce, 0xa6, 0x44, 0xaf, 0x2f, 0x06, 0xfa, 0x45, 0x6c, 0x56, 0x8c, 0xd4, 0xd3, + 0x66, 0xe7, 0x1f, 0x64, 0xe0, 0x3a, 0x63, 0x72, 0x3a, 0xf1, 0xdf, 0xb4, 0x75, 0xb7, 0x0b, 0x65, + 0x39, 0xe7, 0x6f, 0x60, 0x62, 0xad, 0x16, 0x20, 0x41, 0xa6, 0x56, 0xb7, 0x05, 0x89, 0x6b, 0x30, + 0x56, 0xab, 0xdb, 0xfc, 0x02, 0x9a, 0x6e, 0xda, 0xad, 0xc0, 0xb7, 0x09, 0x2c, 0xae, 0xc1, 0xb3, + 0xe7, 0xd0, 0xe0, 0xd6, 0xcf, 0x61, 0x5e, 0x6b, 0x84, 0xcf, 0xfb, 0x32, 0x8c, 0xd7, 0xb0, 0x1f, + 0xf2, 0x66, 0xe8, 0x48, 0x5b, 0xd8, 0x0f, 0x6d, 0x0a, 0x45, 0xb7, 0x61, 0xaa, 0x56, 0xa1, 0xde, + 0x46, 0x6a, 0x5b, 0xcc, 0x30, 0xc5, 0xd4, 0x72, 0x9a, 0x34, 0x92, 0xdc, 0x16, 0x85, 0xd6, 0x7f, + 0xc8, 0x28, 0xd4, 0x09, 0xfa, 0xe8, 0x31, 0x7c, 0x40, 0x8e, 0xc7, 0x84, 0x67, 0xca, 0x10, 0xae, + 0x90, 0x6d, 0x8b, 0x7b, 0x6a, 0xd8, 0xce, 0x67, 0x2b, 0x95, 0xce, 0xe9, 0x29, 0x15, 0x37, 0x73, + 0x0c, 0x49, 0x78, 0x11, 0xe5, 0xcd, 0x1c, 0x27, 0x1d, 0xd8, 0x6a, 0x25, 0xeb, 0x7b, 0x58, 0xd0, + 0xfb, 0xff, 0x46, 0xd9, 0xf3, 0x36, 0xbd, 0xf2, 0x51, 0x2e, 0x4b, 0x11, 0x52, 0x1d, 0x09, 0x5c, + 0xac, 0x3e, 0x81, 0x02, 0xaf, 0x15, 0x2d, 0xcb, 0x5b, 0xc2, 0xb4, 0x63, 0x8b, 0x52, 0x0f, 0x2e, + 0x16, 0xfe, 0xd0, 0x9f, 0x08, 0x57, 0xc5, 0xa8, 0x16, 0xfe, 0x71, 0x06, 0x8a, 0x8f, 0x1f, 0x54, + 0x2a, 0xfd, 0xf0, 0x18, 0x77, 0x43, 0x72, 0x28, 0xc1, 0xb5, 0x63, 0xa7, 0xd3, 0xc1, 0xdd, 0x23, + 0x8c, 0xee, 0xc0, 0xf8, 0xfe, 0x93, 0xfd, 0x3d, 0xee, 0x11, 0x58, 0xe0, 0xc7, 0x71, 0x02, 0x92, + 0x75, 0x6c, 0x5a, 0x03, 0x3d, 0x82, 0x2b, 0x4f, 0x79, 0x38, 0xbf, 0x2c, 0xe2, 0xbe, 0x80, 0x1b, + 0x77, 0x65, 0xa0, 0x7f, 0xcd, 0xc7, 0x6d, 0xd2, 0x8a, 0xd3, 0xa9, 0x04, 0x44, 0x31, 0x90, 0xf9, + 0x49, 0xe2, 0x3d, 0x1c, 0xcf, 0x65, 0x0a, 0x59, 0xeb, 0x0f, 0x32, 0xb0, 0x14, 0xeb, 0x99, 0xe2, + 0xd8, 0x55, 0x3b, 0x36, 0xaf, 0x74, 0x4c, 0x54, 0xd9, 0xba, 0xc4, 0x7b, 0x56, 0xa3, 0xb1, 0xa3, + 0xb4, 0x05, 0xde, 0xa1, 0x77, 0x86, 0x77, 0x28, 0x22, 0x20, 0x11, 0x79, 0xe4, 0x17, 0x85, 0x5b, + 0x97, 0x61, 0x56, 0xe3, 0x80, 0x65, 0xc1, 0x8c, 0xda, 0x32, 0x61, 0x73, 0xcd, 0x6b, 0x4b, 0x36, + 0x93, 0xbf, 0xad, 0x7f, 0x98, 0x81, 0x85, 0xc7, 0x0f, 0x2a, 0x36, 0x3e, 0x72, 0xc9, 0xf2, 0x8b, + 0x58, 0xbc, 0xaa, 0x8d, 0x64, 0x59, 0x1b, 0x49, 0xac, 0xae, 0x1c, 0xd2, 0xe7, 0x89, 0x21, 0x2d, + 0xa7, 0x0d, 0x89, 0x5a, 0x59, 0xae, 0xd7, 0xd5, 0x46, 0xa2, 0x78, 0x3e, 0xfe, 0x49, 0x06, 0xe6, + 0x95, 0x3e, 0xc9, 0xfe, 0x7f, 0xa0, 0x75, 0xe9, 0x7a, 0x4a, 0x97, 0x12, 0x4c, 0xae, 0x26, 0x7a, + 0xf4, 0xf6, 0xb0, 0x1e, 0x8d, 0xe4, 0xf1, 0x9f, 0x64, 0x60, 0x31, 0x95, 0x07, 0xe8, 0x2a, 0xd9, + 0x35, 0x5a, 0x3e, 0x0e, 0x39, 0x7b, 0xf9, 0x17, 0x81, 0x6f, 0x07, 0x41, 0x9f, 0xbf, 0xb5, 0xc8, + 0xdb, 0xfc, 0x0b, 0xbd, 0x0d, 0xb3, 0x7b, 0xd8, 0x77, 0xbd, 0x76, 0x1d, 0xb7, 0xbc, 0x6e, 0x9b, + 0x79, 0x84, 0x67, 0x6d, 0x1d, 0x88, 0x96, 0x21, 0x5f, 0xe9, 0x1c, 0x79, 0xbe, 0x1b, 0x1e, 0x33, + 0xe7, 0x53, 0xde, 0x8e, 0x00, 0x84, 0xf6, 0xba, 0x7b, 0xe4, 0x86, 0xec, 0x6e, 0x6d, 0xd6, 0xe6, + 0x5f, 0xa8, 0x08, 0x53, 0x95, 0x56, 0xcb, 0xeb, 0x77, 0x43, 0xea, 0x01, 0xcd, 0xdb, 0xe2, 0x93, + 0x60, 0x7c, 0x6b, 0x53, 0x21, 0xa0, 0xd1, 0x50, 0x36, 0xff, 0xb2, 0xde, 0x83, 0x85, 0x34, 0x3e, + 0xa6, 0x8a, 0xcc, 0xdf, 0xc8, 0xc2, 0x7c, 0xa5, 0xdd, 0x7e, 0xfc, 0xa0, 0xb2, 0x8e, 0x55, 0xe3, + 0xe3, 0x43, 0x18, 0xdf, 0xee, 0xba, 0x21, 0xdf, 0x35, 0x57, 0xf8, 0xf4, 0xa4, 0xd4, 0x24, 0xb5, + 0xc8, 0x0c, 0x91, 0xff, 0x91, 0x0d, 0xf3, 0x1b, 0x3f, 0xba, 0x41, 0xe8, 0x76, 0x8f, 0xe8, 0x9c, + 0xb3, 0x86, 0xf9, 0x1c, 0x0b, 0x22, 0x86, 0xe5, 0xb6, 0x75, 0xc9, 0x4e, 0x43, 0x46, 0xfb, 0x70, + 0x75, 0x17, 0xbf, 0x48, 0x11, 0x21, 0x19, 0xcc, 0x24, 0xc9, 0xa6, 0x48, 0x8e, 0x01, 0x57, 0x95, + 0xd0, 0xbf, 0x93, 0xa5, 0x11, 0x72, 0xca, 0xc0, 0x78, 0xcb, 0x07, 0xb0, 0xa0, 0x74, 0x28, 0xd2, + 0x38, 0x19, 0x1e, 0x3b, 0x9d, 0x3a, 0x1c, 0x75, 0x21, 0xa5, 0xa2, 0xa3, 0xa7, 0xb0, 0xa4, 0x77, + 0x2a, 0xa2, 0xac, 0x2f, 0x86, 0xb4, 0x2a, 0x5b, 0x97, 0x6c, 0x13, 0x36, 0x5a, 0x85, 0xb1, 0x4a, + 0xeb, 0x84, 0xb3, 0x25, 0x7d, 0xca, 0xd8, 0xc8, 0x2a, 0xad, 0x13, 0x1a, 0x6d, 0xda, 0x3a, 0xd1, + 0xd6, 0xc3, 0x7f, 0xcc, 0xc0, 0x92, 0x61, 0x86, 0xd1, 0x0a, 0x00, 0x03, 0x2a, 0xba, 0x5d, 0x81, + 0x90, 0x5d, 0x95, 0x7d, 0xd1, 0x0b, 0xc7, 0x31, 0x7a, 0x7f, 0x2d, 0xe2, 0x82, 0xa2, 0x02, 0x5b, + 0xa9, 0x84, 0xf6, 0x60, 0x9a, 0x7d, 0xb1, 0xf0, 0xa4, 0x71, 0x8a, 0x83, 0x34, 0x1c, 0x16, 0x8f, + 0x44, 0x63, 0x0e, 0xda, 0x14, 0xd0, 0x8c, 0x87, 0x25, 0xa9, 0x24, 0xf8, 0xd1, 0xaf, 0x16, 0x1f, + 0x85, 0x1c, 0x34, 0xba, 0x03, 0x93, 0x0c, 0xc8, 0xe7, 0x50, 0xbc, 0x7a, 0x89, 0x2a, 0xf3, 0x72, + 0xeb, 0x0f, 0x33, 0xc2, 0xa3, 0x93, 0x58, 0x1a, 0x9f, 0x68, 0x4b, 0xe3, 0x2d, 0xd9, 0xe1, 0xb4, + 0xca, 0xda, 0xea, 0xa8, 0xc2, 0xf4, 0xab, 0xac, 0x0a, 0x15, 0x49, 0x95, 0xdb, 0x7f, 0x91, 0x11, + 0x67, 0xd1, 0xa4, 0xe8, 0x6e, 0xc0, 0xcc, 0xab, 0x89, 0xac, 0x86, 0x86, 0x3e, 0x62, 0x12, 0x95, + 0x1d, 0x3e, 0xd2, 0xa1, 0x42, 0xf5, 0xa5, 0x70, 0x5a, 0xbd, 0x8a, 0x58, 0x59, 0xcb, 0x29, 0xd8, + 0xb2, 0x39, 0xab, 0x9f, 0x28, 0xad, 0xbf, 0xec, 0xb6, 0xc4, 0x3c, 0xdd, 0x8e, 0x5f, 0xb2, 0x1b, + 0x6f, 0x50, 0xd5, 0x3e, 0x64, 0x23, 0x3f, 0x06, 0x17, 0x39, 0x6a, 0xd2, 0xaa, 0x9d, 0x3a, 0x8b, + 0xad, 0x93, 0x57, 0x69, 0xb4, 0x06, 0xb3, 0xbb, 0xf8, 0x45, 0xa2, 0x5d, 0x7a, 0x2f, 0xd5, 0xc5, + 0x2f, 0x9a, 0x4a, 0xdb, 0x8a, 0xb4, 0xeb, 0x38, 0xe8, 0x10, 0xe6, 0x84, 0x2e, 0x38, 0xaf, 0x4a, + 0x64, 0x11, 0x97, 0xa4, 0x85, 0xd3, 0x67, 0x4e, 0xd3, 0xe7, 0x50, 0x35, 0x54, 0x52, 0xa7, 0x68, + 0xed, 0x41, 0x31, 0x39, 0x56, 0x2e, 0x65, 0x1f, 0x8e, 0x5a, 0x4e, 0xec, 0x54, 0xd5, 0xd6, 0x97, + 0xd6, 0x16, 0x75, 0x00, 0xc8, 0x3a, 0xf2, 0xe8, 0x72, 0x3f, 0xce, 0x3a, 0x1a, 0x45, 0x26, 0x58, + 0xa7, 0x86, 0x74, 0x47, 0x61, 0x16, 0x8b, 0x31, 0x4a, 0xbc, 0x63, 0xef, 0xc1, 0x14, 0x07, 0xc9, + 0x50, 0xf9, 0xf8, 0x42, 0x17, 0x15, 0xac, 0x7f, 0x9a, 0x81, 0x6b, 0x07, 0x01, 0xf6, 0xeb, 0x6e, + 0xf7, 0xa8, 0x83, 0x0f, 0x02, 0x3d, 0xc8, 0xe1, 0xb7, 0xb5, 0xc5, 0xbe, 0x64, 0x08, 0x9e, 0xfc, + 0xff, 0xb5, 0xc4, 0xff, 0x79, 0x06, 0x4a, 0x69, 0x7d, 0x7b, 0xb3, 0xab, 0xfc, 0x2e, 0x3f, 0x6b, + 0xb0, 0xde, 0x16, 0x39, 0xba, 0x6c, 0x53, 0x0c, 0x96, 0x0c, 0x92, 0xfc, 0xaf, 0x2d, 0xef, 0xff, + 0x93, 0x81, 0x85, 0xed, 0x80, 0x76, 0xff, 0x17, 0x7d, 0xd7, 0xc7, 0x6d, 0xc1, 0xb8, 0xbb, 0x69, + 0x21, 0xb6, 0x74, 0x5e, 0xb7, 0x2e, 0xa5, 0x85, 0xd0, 0x7e, 0xa8, 0x04, 0x11, 0x66, 0x87, 0xc5, + 0xce, 0x6a, 0xef, 0x35, 0x6e, 0xc3, 0xf8, 0x2e, 0x31, 0x69, 0xc6, 0xb8, 0xfc, 0x31, 0x0c, 0x02, + 0xa2, 0xf1, 0x7e, 0xa4, 0xcb, 0xe4, 0x03, 0x3d, 0x48, 0x44, 0x15, 0x8e, 0x8f, 0x8e, 0x0d, 0x4d, + 0x3e, 0x34, 0xa9, 0xe6, 0x60, 0x72, 0xdf, 0xf1, 0x8f, 0x70, 0x68, 0xfd, 0x0c, 0x4a, 0xfc, 0x32, + 0x8f, 0xf9, 0xc8, 0xe8, 0x95, 0x5f, 0x10, 0xf9, 0x6e, 0x86, 0x5d, 0xc0, 0xad, 0x00, 0xd4, 0x43, + 0xc7, 0x0f, 0xb7, 0xbb, 0x6d, 0xfc, 0x23, 0x1d, 0xed, 0x84, 0xad, 0x40, 0xac, 0x8f, 0x20, 0x2f, + 0x87, 0x40, 0xcf, 0x53, 0x8a, 0xd5, 0x46, 0x87, 0xb3, 0xa0, 0xc5, 0x39, 0x8a, 0xe0, 0xc6, 0x35, + 0x58, 0x8c, 0x4d, 0x05, 0x97, 0x93, 0x12, 0x99, 0x30, 0x06, 0x63, 0x17, 0xfd, 0xb6, 0xfc, 0xb6, + 0x6a, 0x70, 0x25, 0x31, 0xd3, 0x08, 0xd1, 0xd8, 0x55, 0x76, 0xf8, 0x24, 0x4a, 0xbd, 0x5e, 0xdf, + 0x22, 0xb0, 0xfd, 0x9d, 0x3a, 0x8b, 0xe3, 0x21, 0xb0, 0xfd, 0x9d, 0x7a, 0x75, 0x92, 0x49, 0x8e, + 0xf5, 0xaf, 0xb3, 0xf4, 0x08, 0x99, 0xe0, 0x41, 0xcc, 0x15, 0xa1, 0xba, 0x43, 0xaa, 0x90, 0xa7, + 0x23, 0x5e, 0x17, 0xf1, 0x6e, 0xc3, 0x6f, 0x00, 0x72, 0xbf, 0x1c, 0x94, 0x2f, 0x51, 0xb7, 0x7f, + 0x84, 0x86, 0xbe, 0x86, 0xa9, 0x8d, 0x6e, 0x9b, 0x52, 0x18, 0xbb, 0x00, 0x05, 0x81, 0x44, 0xe6, + 0x81, 0x76, 0x99, 0x98, 0x23, 0xfc, 0xbc, 0x6e, 0x2b, 0x10, 0xca, 0x66, 0xf7, 0xd4, 0x65, 0xf7, + 0xbc, 0x13, 0x36, 0xfb, 0x20, 0xdc, 0xa4, 0x5d, 0x10, 0xcf, 0x17, 0xf2, 0xb6, 0xfc, 0x46, 0x16, + 0x4c, 0x3c, 0xf1, 0xdb, 0x3c, 0x98, 0x7c, 0x6e, 0x75, 0x46, 0xbc, 0xe7, 0x26, 0x30, 0x9b, 0x15, + 0x59, 0xff, 0x8b, 0xde, 0xbd, 0x84, 0xa9, 0x72, 0xa3, 0x71, 0x25, 0xf3, 0xda, 0x5c, 0xc9, 0xbe, + 0x0a, 0x57, 0xe4, 0xa8, 0xc7, 0x4c, 0xa3, 0x1e, 0x37, 0x8d, 0x7a, 0xc2, 0x3c, 0xea, 0x4d, 0x98, + 0x64, 0x43, 0x45, 0xb7, 0x60, 0x62, 0x3b, 0xc4, 0xa7, 0x91, 0x6b, 0x41, 0xbd, 0x3d, 0xb7, 0x59, + 0x19, 0x39, 0xf5, 0xec, 0x38, 0x41, 0x28, 0x22, 0xc7, 0xf2, 0xb6, 0xf8, 0xb4, 0xfe, 0x34, 0x03, + 0x85, 0x1d, 0x37, 0x08, 0xc9, 0x42, 0x38, 0xa7, 0xac, 0xc9, 0x11, 0x65, 0x4d, 0x23, 0x1a, 0x8b, + 0x8d, 0xe8, 0x0b, 0x98, 0xa4, 0x01, 0x8d, 0x01, 0x7f, 0xaa, 0x74, 0x8b, 0x0f, 0x29, 0xde, 0x30, + 0x0b, 0x7b, 0x0c, 0xe8, 0x93, 0x22, 0x9b, 0xa3, 0x94, 0x3e, 0x83, 0x69, 0x05, 0x7c, 0xa1, 0x97, + 0x46, 0xdf, 0xc1, 0x15, 0xa5, 0x09, 0xe9, 0x87, 0x18, 0xe1, 0xad, 0x96, 0xde, 0x50, 0xc2, 0xb6, + 0x5d, 0xfc, 0xa3, 0xca, 0x36, 0xfe, 0x69, 0xfd, 0x40, 0xe3, 0x71, 0x77, 0xbc, 0xd6, 0x89, 0xe2, + 0x2b, 0x9c, 0x62, 0xca, 0x2c, 0xee, 0x72, 0x27, 0xb5, 0x58, 0x89, 0x2d, 0x6a, 0xa0, 0x9b, 0x30, + 0xbd, 0xdd, 0x7d, 0xe0, 0xf9, 0x2d, 0xfc, 0xa4, 0xdb, 0x61, 0xd4, 0x73, 0xb6, 0x0a, 0xe2, 0x6e, + 0x24, 0xde, 0x42, 0xe4, 0x46, 0xa2, 0x80, 0x98, 0x1b, 0x89, 0xbd, 0x94, 0xb4, 0x59, 0x19, 0xf7, + 0x52, 0x91, 0xbf, 0x87, 0xf9, 0x90, 0xa4, 0xb3, 0x69, 0x54, 0xc5, 0x43, 0xb8, 0x66, 0xe3, 0x5e, + 0xc7, 0x21, 0xb6, 0xe2, 0xa9, 0xc7, 0xea, 0xcb, 0x31, 0xdf, 0x4c, 0x09, 0x15, 0xd3, 0x6f, 0x9c, + 0x64, 0x97, 0xb3, 0x43, 0xba, 0x7c, 0x0a, 0x6f, 0x6d, 0xe2, 0x30, 0xf5, 0xb9, 0x63, 0x34, 0xf8, + 0x2d, 0xc8, 0xf1, 0x90, 0x7c, 0x31, 0xfe, 0x51, 0x2f, 0x2d, 0xf9, 0xf5, 0x0b, 0xa7, 0x23, 0xff, + 0xb2, 0xbe, 0x81, 0xb2, 0xa9, 0xb9, 0xf3, 0x45, 0x08, 0xb9, 0x70, 0xd3, 0x4c, 0x40, 0x5a, 0x13, + 0x53, 0xbc, 0x41, 0x79, 0xea, 0x1f, 0xde, 0x5b, 0xe9, 0x90, 0xa7, 0xf6, 0x14, 0xff, 0xc3, 0xaa, + 0x8a, 0x10, 0x84, 0xd7, 0xe8, 0x6e, 0x93, 0x5e, 0x19, 0xe8, 0x04, 0x22, 0xbe, 0x56, 0x20, 0x27, + 0x60, 0xb1, 0x3b, 0x83, 0xc4, 0x4b, 0x52, 0xca, 0xd0, 0xb6, 0x20, 0x20, 0xd1, 0xac, 0x1f, 0x84, + 0x63, 0x5f, 0xc7, 0x38, 0x5f, 0xd8, 0xe9, 0x79, 0x3c, 0xf9, 0x96, 0x07, 0xd7, 0x74, 0xda, 0xaa, + 0x7b, 0xba, 0xa0, 0xb8, 0xa7, 0x99, 0x57, 0x9a, 0xc8, 0xa5, 0xbd, 0xb3, 0xd1, 0x6d, 0xf7, 0x3c, + 0xb7, 0x1b, 0xf2, 0xc5, 0xab, 0x82, 0xd0, 0x8a, 0xea, 0x84, 0x9e, 0x49, 0xc6, 0xe9, 0xde, 0x87, + 0x52, 0x5a, 0x83, 0x8a, 0xef, 0x47, 0xfa, 0x93, 0x99, 0x1d, 0x67, 0x1d, 0xc3, 0x82, 0x96, 0x9b, + 0x23, 0x4a, 0x36, 0x10, 0xe5, 0x24, 0xc9, 0x57, 0xbf, 0xfc, 0xf5, 0xa0, 0xfc, 0xe9, 0x45, 0x82, + 0x41, 0x05, 0xcd, 0x7d, 0x19, 0x6a, 0x6c, 0x2d, 0xc1, 0x58, 0xcd, 0xde, 0xa1, 0xc3, 0xb6, 0x77, + 0xe4, 0xb0, 0xed, 0x1d, 0xeb, 0xd7, 0x19, 0x28, 0xd7, 0x8e, 0x9d, 0xee, 0x11, 0xb5, 0x3d, 0x14, + 0x73, 0x55, 0xb9, 0x57, 0x3d, 0xef, 0x91, 0x6a, 0x15, 0xa6, 0x77, 0xf1, 0x0b, 0x11, 0x26, 0xcd, + 0x03, 0x8e, 0xa9, 0xfb, 0x9d, 0x1c, 0x77, 0x7a, 0x1c, 0x6e, 0xab, 0x95, 0xd0, 0x5f, 0x7d, 0x75, + 0xe7, 0x12, 0x7b, 0xa1, 0x1f, 0x9d, 0xa4, 0x58, 0x69, 0xda, 0x91, 0xca, 0xd0, 0x84, 0xf5, 0x6f, + 0x33, 0x70, 0xd3, 0x3c, 0x78, 0x3e, 0x71, 0xeb, 0x5a, 0x9e, 0x83, 0x21, 0x37, 0xc2, 0xf4, 0xc8, + 0xaa, 0xe4, 0x39, 0x88, 0xe7, 0x36, 0xb0, 0x71, 0xcb, 0x7b, 0x8e, 0xfd, 0x97, 0x31, 0x3f, 0xbb, + 0x00, 0xd7, 0xc8, 0x96, 0x23, 0xb2, 0xc4, 0x30, 0x90, 0xf6, 0xb4, 0x91, 0xc3, 0xac, 0xff, 0x9c, + 0x81, 0xeb, 0x74, 0x9b, 0xe4, 0x5e, 0x48, 0x51, 0x70, 0xf1, 0xf8, 0x81, 0x8f, 0x60, 0x46, 0x6d, + 0x9c, 0x4f, 0x18, 0x7d, 0x18, 0x2d, 0x7a, 0xd0, 0x6c, 0x79, 0x6d, 0x6c, 0x6b, 0xd5, 0xd0, 0x36, + 0x4c, 0xf3, 0x6f, 0xc5, 0xd5, 0xb4, 0xa8, 0x64, 0x4d, 0xa1, 0xf2, 0xc0, 0x3c, 0x47, 0x74, 0xf6, + 0x39, 0xb1, 0x26, 0x0d, 0x7d, 0x57, 0x71, 0xad, 0x5f, 0x65, 0x61, 0xb9, 0x81, 0x7d, 0xf7, 0xd9, + 0x4b, 0xc3, 0x60, 0x9e, 0xc0, 0x82, 0x00, 0xd1, 0x31, 0xeb, 0x72, 0xc8, 0x9e, 0xa8, 0x89, 0xae, + 0x06, 0xa4, 0x42, 0x53, 0x8a, 0x65, 0x2a, 0xe2, 0x05, 0x1e, 0x6d, 0x7e, 0x08, 0x39, 0x29, 0xca, + 0x63, 0x94, 0x33, 0x74, 0x6e, 0x84, 0x18, 0xeb, 0xef, 0xd7, 0xa5, 0x3c, 0xff, 0x6d, 0xf3, 0x75, + 0x06, 0x3f, 0xf1, 0x8c, 0x38, 0x8c, 0x32, 0xa9, 0x26, 0x12, 0xed, 0x28, 0xa5, 0x29, 0x52, 0xbd, + 0x75, 0xc9, 0x36, 0xb5, 0x54, 0x9d, 0x86, 0x7c, 0x85, 0x5e, 0xb6, 0x90, 0x03, 0xc6, 0xff, 0xce, + 0xc2, 0x8a, 0x08, 0x29, 0x34, 0xb0, 0xf9, 0x3b, 0x58, 0x12, 0xa0, 0x4a, 0xaf, 0xe7, 0x7b, 0xcf, + 0x71, 0x5b, 0xe7, 0x34, 0x7b, 0x26, 0x2a, 0x38, 0xed, 0xf0, 0x3a, 0x11, 0xb3, 0x4d, 0xe8, 0x6f, + 0xc6, 0xcd, 0xf2, 0xb5, 0xae, 0x58, 0xd8, 0x6c, 0x50, 0xa7, 0xa4, 0xaa, 0x58, 0xf4, 0x04, 0x3f, + 0xaa, 0x92, 0x69, 0x27, 0xdc, 0x34, 0xe3, 0xaf, 0xeb, 0xa6, 0x21, 0x47, 0x53, 0x9d, 0x66, 0x75, + 0x0e, 0x66, 0x76, 0xf1, 0x8b, 0x88, 0xef, 0xbf, 0x97, 0x81, 0x59, 0x6d, 0x71, 0xa3, 0x77, 0x61, + 0x82, 0xfe, 0x41, 0x37, 0x4d, 0xfe, 0x56, 0x86, 0x2c, 0x30, 0xed, 0xad, 0x0c, 0xab, 0xba, 0x0d, + 0x53, 0x2c, 0x7c, 0xa6, 0x7d, 0x8e, 0x33, 0x84, 0x8c, 0xce, 0x6a, 0x31, 0x14, 0x76, 0x9c, 0xe0, + 0xf8, 0xd6, 0x23, 0x78, 0x8b, 0x47, 0xe2, 0xe8, 0x93, 0x5f, 0x53, 0xed, 0xf7, 0x73, 0xea, 0x78, + 0xcb, 0x81, 0x95, 0x4d, 0x1c, 0x57, 0x3d, 0x5a, 0xf4, 0xda, 0x37, 0x70, 0x59, 0x83, 0x4b, 0x8a, + 0x34, 0x9e, 0x5e, 0xca, 0x90, 0x24, 0x1d, 0xaf, 0x6d, 0xdd, 0x4c, 0x6b, 0x42, 0xed, 0xac, 0x85, + 0xe1, 0x32, 0x3d, 0x29, 0xcb, 0x1b, 0xa7, 0xe0, 0x02, 0x5a, 0xef, 0x8e, 0xb2, 0xae, 0x99, 0xc6, + 0x63, 0x4f, 0x31, 0xc5, 0xf6, 0x24, 0x4b, 0xad, 0x59, 0x98, 0xae, 0x79, 0xdd, 0x10, 0xff, 0x48, + 0x1f, 0x43, 0x58, 0x73, 0x30, 0x23, 0x8a, 0x3a, 0x38, 0x08, 0xac, 0x7f, 0x36, 0x06, 0x16, 0x67, + 0x6c, 0x9a, 0x97, 0x47, 0xf0, 0xe3, 0x30, 0xd1, 0x59, 0xbe, 0x89, 0x5c, 0x55, 0x7d, 0x59, 0x51, + 0x29, 0x93, 0x3c, 0xfa, 0x78, 0xa5, 0x15, 0x41, 0x35, 0xc9, 0x4b, 0x8c, 0xfe, 0xe7, 0x06, 0x35, + 0xc9, 0x16, 0x1b, 0x4d, 0x1f, 0x62, 0x50, 0x93, 0x1a, 0xdd, 0x74, 0x95, 0x69, 0x6b, 0x6c, 0xe0, + 0xfb, 0x32, 0x92, 0xa1, 0xdf, 0xb2, 0x84, 0xa7, 0xdc, 0x62, 0x80, 0x66, 0x22, 0x65, 0x96, 0x4a, + 0x04, 0x1d, 0xe8, 0xbc, 0xe4, 0xeb, 0x51, 0xdc, 0xf0, 0xaa, 0x45, 0x8c, 0x6a, 0x4f, 0x81, 0xe8, + 0x19, 0xc8, 0xb4, 0xba, 0x8a, 0xe7, 0xee, 0x1f, 0x65, 0xe0, 0x3a, 0x9b, 0x9d, 0x3d, 0xdf, 0x7d, + 0xee, 0x76, 0xf0, 0x11, 0xd6, 0xc4, 0xb4, 0x9f, 0x7e, 0x53, 0x96, 0x39, 0x97, 0x8e, 0xa6, 0x49, + 0x1b, 0x30, 0x47, 0x37, 0x39, 0x72, 0xd3, 0xe8, 0x5b, 0x83, 0x0c, 0xac, 0x88, 0x37, 0x65, 0xb1, + 0xeb, 0xa3, 0x8b, 0x9a, 0x5b, 0x55, 0xed, 0xc6, 0x27, 0x6b, 0xb8, 0xf1, 0xd1, 0x3c, 0xe9, 0xe1, + 0x88, 0x2b, 0xa0, 0xb1, 0xd7, 0xbe, 0x02, 0xb2, 0x7e, 0x77, 0x0c, 0xae, 0xec, 0x39, 0x47, 0x6e, 0x97, 0xe8, 0x1e, 0x91, 0x47, 0x05, 0x55, 0x12, 0xe9, 0xa8, 0x86, 0x47, 0x03, 0xa5, 0xe4, 0x9b, 0x5a, 0x55, 0x33, 0xc3, 0x64, 0x4d, 0x71, 0xe2, 0x7a, 0xfe, 0x97, 0xcf, 0x34, 0xef, 0x64, 0x22, 0x20, 0x8c, 0xbe, 0x35, 0xea, 0x7a, 0xed, 0x58, 0x8a, 0x36, 0xea, 0xe1, 0x7b, 0x02, 0xd3, 0x4a, 0x54, 0x17, 0x17, 0xd0, 0x04, 0x05, 0xca, 0x96, 0x93, 0xfe, 0x21, 0x4e, 0x4d, 0xc7, 0xa3, 0x52, - 0xa8, 0x02, 0xe4, 0x44, 0xf6, 0x3f, 0xeb, 0x5f, 0x4e, 0xc0, 0xc2, 0x8e, 0x1b, 0x84, 0x82, 0x3f, - 0x41, 0xa4, 0x3c, 0x67, 0x04, 0x4c, 0x39, 0x01, 0x70, 0x3b, 0x87, 0xc1, 0x9b, 0xb1, 0x64, 0x84, - 0x1a, 0x02, 0xfa, 0x48, 0xf5, 0xc3, 0x64, 0x95, 0x14, 0x05, 0xc9, 0x3c, 0x72, 0xaa, 0x83, 0xe6, - 0x5d, 0xcd, 0xe5, 0xc4, 0x76, 0xa6, 0x0e, 0x01, 0xa8, 0x3b, 0x13, 0xf3, 0xda, 0xac, 0xc5, 0xfd, - 0x50, 0xac, 0x01, 0xa6, 0x56, 0x4e, 0xb0, 0x66, 0xb4, 0x4a, 0x77, 0xce, 0x81, 0x74, 0xe7, 0x4c, - 0xd0, 0xf3, 0xe2, 0x4f, 0x14, 0x77, 0x4e, 0x9c, 0x09, 0xaa, 0x4b, 0x87, 0x3d, 0x8a, 0xed, 0x50, - 0x80, 0xfa, 0x28, 0x96, 0x55, 0x41, 0xfb, 0x30, 0xbf, 0xe7, 0xe3, 0x36, 0x5d, 0x9c, 0x1b, 0x3f, - 0xf6, 0x7c, 0x6e, 0xa4, 0x53, 0xa7, 0x20, 0xcb, 0xd7, 0xd4, 0x13, 0xc5, 0x4d, 0x2c, 0xcb, 0xd5, - 0x35, 0x9a, 0x82, 0x8e, 0x36, 0x60, 0xae, 0x8e, 0x1d, 0xbf, 0x75, 0xfc, 0x08, 0xbf, 0x24, 0xaa, - 0x25, 0x28, 0x4e, 0x45, 0x39, 0x2e, 0x02, 0x5a, 0x42, 0x06, 0x4a, 0x8b, 0xd4, 0x8b, 0x1b, 0x1d, - 0x09, 0xfd, 0x14, 0x26, 0xeb, 0x9e, 0x1f, 0x56, 0x5f, 0xc6, 0x12, 0x0b, 0x32, 0x60, 0xf5, 0x9a, - 0xc8, 0xf3, 0x11, 0x78, 0x7e, 0xd8, 0x3c, 0x54, 0xf9, 0xc6, 0xf1, 0xd0, 0x03, 0x62, 0xb7, 0x10, - 0x5b, 0x2a, 0x74, 0x3a, 0x35, 0x1a, 0x80, 0xc0, 0x9e, 0x35, 0x71, 0xdb, 0x84, 0x1a, 0x60, 0xa1, - 0xd3, 0x69, 0xd2, 0x9d, 0x52, 0xbf, 0x42, 0x52, 0xb1, 0x5e, 0xc7, 0x1f, 0xf6, 0xc7, 0x19, 0x58, - 0x8c, 0x4d, 0x12, 0x3f, 0x17, 0x3d, 0x81, 0xbc, 0x04, 0x72, 0x2f, 0x40, 0x51, 0xea, 0xef, 0xd8, - 0xfa, 0x67, 0x22, 0x22, 0x24, 0x58, 0x65, 0x5a, 0x44, 0x03, 0xdd, 0x8f, 0xb9, 0xce, 0x98, 0xbd, - 0xdd, 0x25, 0x9b, 0x89, 0x2e, 0x56, 0xa2, 0x1a, 0xfa, 0x0c, 0x40, 0xe1, 0x0d, 0x13, 0x5d, 0x9a, - 0x6d, 0x2e, 0x9d, 0x2d, 0x4a, 0x65, 0xeb, 0x4f, 0x27, 0xc5, 0xf6, 0xc0, 0x4f, 0x68, 0xfb, 0xbe, - 0xd3, 0x3a, 0x89, 0x22, 0x0b, 0x3f, 0x4a, 0x86, 0xf1, 0x9d, 0x67, 0x1d, 0xdd, 0xd6, 0x1e, 0xfc, - 0x9a, 0x73, 0x87, 0x46, 0x6f, 0xbf, 0xc7, 0xce, 0xf1, 0xf6, 0xfb, 0x1e, 0x4c, 0x6d, 0x77, 0x9f, - 0xbb, 0xc4, 0x18, 0x64, 0x31, 0x6d, 0xd4, 0x94, 0x72, 0x19, 0x48, 0x65, 0x0c, 0xaf, 0x85, 0x3e, - 0x83, 0xdc, 0x96, 0x17, 0x84, 0xd4, 0x1a, 0x9a, 0x88, 0x0c, 0xee, 0x90, 0xba, 0x12, 0x9b, 0xc7, - 0xbc, 0x48, 0x5d, 0xa9, 0xa2, 0x3a, 0xfa, 0x18, 0xa6, 0x2a, 0xed, 0x36, 0x59, 0x0a, 0x7c, 0x19, - 0xd1, 0xc4, 0x83, 0x1c, 0xd3, 0x61, 0x25, 0x6a, 0x93, 0xbc, 0x32, 0xfa, 0x52, 0xf7, 0xeb, 0x4d, - 0x45, 0x99, 0x11, 0xd2, 0x93, 0x70, 0xea, 0x3e, 0xbf, 0x77, 0xc5, 0x7d, 0x4a, 0x2e, 0xca, 0x35, - 0x41, 0xf3, 0x46, 0x68, 0xfa, 0x87, 0x5e, 0xc7, 0x6c, 0x43, 0x7e, 0xbb, 0xeb, 0x86, 0x2e, 0x7d, - 0x6d, 0x9f, 0xd7, 0xf6, 0x81, 0x3d, 0xc7, 0x0f, 0xdd, 0x96, 0xdb, 0x73, 0xba, 0x21, 0x9b, 0x2d, - 0x57, 0x54, 0x54, 0x67, 0x4b, 0x62, 0xab, 0x79, 0x79, 0xe0, 0x8d, 0xe5, 0xe5, 0x49, 0x4d, 0x6d, - 0x33, 0xfd, 0xea, 0xa9, 0x6d, 0xd6, 0xd8, 0x5c, 0x52, 0xdb, 0x6b, 0x26, 0x12, 0x44, 0xea, 0xee, - 0xd2, 0x8d, 0x2c, 0x5b, 0x56, 0x44, 0x37, 0xe9, 0xeb, 0xfa, 0xd9, 0x28, 0x3c, 0x54, 0xbb, 0xbf, - 0xcd, 0x6e, 0xaf, 0xa3, 0x26, 0xcc, 0x90, 0xda, 0x7b, 0x5e, 0xc7, 0x6d, 0xb9, 0x38, 0x28, 0xce, - 0x69, 0xfe, 0x51, 0x7d, 0x51, 0xd0, 0x4a, 0x2f, 0xeb, 0x38, 0x64, 0x3b, 0x11, 0x6d, 0xba, 0xc7, - 0x11, 0xd5, 0x9d, 0x48, 0x25, 0x68, 0xd9, 0x50, 0x8c, 0x2e, 0x59, 0x62, 0xab, 0xeb, 0xe3, 0x64, - 0xa4, 0x3e, 0xcd, 0xe8, 0x16, 0x45, 0xea, 0xab, 0x13, 0x16, 0xc5, 0xec, 0x1f, 0xc0, 0x75, 0x1b, - 0x9f, 0x7a, 0xcf, 0xf1, 0x9b, 0x25, 0xfb, 0x73, 0xb8, 0xa6, 0x13, 0x3c, 0xe8, 0xb5, 0xe9, 0xcb, - 0x3f, 0x76, 0x9b, 0x93, 0x9a, 0x13, 0x82, 0x23, 0xb0, 0x9c, 0x10, 0xec, 0xa1, 0x31, 0xf9, 0x53, - 0x95, 0x57, 0x5a, 0x66, 0x79, 0xb0, 0xac, 0x13, 0xaf, 0xb4, 0xdb, 0x8a, 0xa0, 0x12, 0x43, 0x43, - 0xf9, 0x8c, 0x59, 0x36, 0xaa, 0x44, 0x53, 0xcd, 0xd6, 0x8b, 0x00, 0xea, 0x5a, 0x52, 0xea, 0x59, - 0x18, 0xca, 0x71, 0xf6, 0x10, 0x96, 0xa9, 0x6d, 0x56, 0x61, 0x56, 0xf9, 0x94, 0x07, 0x05, 0xba, - 0xd4, 0x95, 0x16, 0x74, 0x86, 0xe9, 0x28, 0xd6, 0xbf, 0x1a, 0x83, 0xeb, 0x9c, 0x4f, 0x6f, 0x72, - 0x32, 0xd0, 0x0f, 0x30, 0xad, 0xb0, 0x9f, 0xf3, 0xe3, 0xa6, 0xb8, 0x13, 0x37, 0x4d, 0x13, 0x53, - 0x35, 0x7d, 0x0a, 0x68, 0xc6, 0x66, 0x82, 0x58, 0x62, 0xea, 0x8c, 0x76, 0x60, 0x4e, 0x9f, 0x03, - 0x6e, 0x1f, 0xde, 0x4a, 0x6d, 0x44, 0xaf, 0x2a, 0x1e, 0x2e, 0xb7, 0x9b, 0xa9, 0x33, 0x41, 0xb3, - 0x63, 0xea, 0xf3, 0xfb, 0x23, 0x5c, 0x49, 0x4c, 0x00, 0x37, 0x27, 0x6f, 0xa7, 0x36, 0x98, 0xa8, - 0xcd, 0xf4, 0x86, 0x4f, 0xc1, 0xc6, 0x66, 0x93, 0x8d, 0x54, 0x73, 0x30, 0xc9, 0x86, 0x4d, 0xd6, - 0xcd, 0x9e, 0x8f, 0x03, 0xdc, 0x6d, 0x61, 0x35, 0xf0, 0xe0, 0x75, 0xd7, 0xcd, 0x7f, 0xca, 0x40, - 0x31, 0x8d, 0x6e, 0x1d, 0x77, 0xdb, 0x68, 0x0f, 0x0a, 0xf1, 0x86, 0xb8, 0xd1, 0x6f, 0x09, 0x33, - 0xc1, 0xdc, 0xa5, 0xad, 0x4b, 0x76, 0x02, 0x9b, 0x68, 0x56, 0x05, 0x76, 0xc1, 0x08, 0x8f, 0x24, - 0xaa, 0x72, 0x5a, 0x7c, 0xef, 0x3d, 0xc8, 0xcb, 0x94, 0xdf, 0x28, 0x07, 0xe3, 0xdb, 0xbb, 0xdb, - 0xfb, 0x2c, 0x85, 0xd4, 0xde, 0xc1, 0x7e, 0x21, 0x83, 0x00, 0x26, 0xd7, 0x37, 0x76, 0x36, 0xf6, - 0x37, 0x0a, 0xd9, 0xf7, 0x9a, 0xea, 0xb9, 0x0b, 0x5d, 0x87, 0xa5, 0xf5, 0x8d, 0xc6, 0x76, 0x6d, - 0xa3, 0xb9, 0xff, 0x17, 0xf6, 0x36, 0x9a, 0x07, 0xbb, 0xf5, 0xbd, 0x8d, 0xda, 0xf6, 0x83, 0xed, - 0x8d, 0xf5, 0xc2, 0x25, 0xb4, 0x00, 0x05, 0xb5, 0x70, 0xff, 0xc9, 0xfe, 0x5e, 0x21, 0x83, 0x8a, - 0xb0, 0xa0, 0x42, 0x9f, 0x6e, 0x54, 0x2b, 0x07, 0xfb, 0x5b, 0xbb, 0x85, 0x31, 0x6b, 0x3c, 0x97, - 0x2d, 0x64, 0xdf, 0xfb, 0x41, 0x3b, 0x94, 0xa1, 0x65, 0x28, 0xf2, 0xea, 0x07, 0xf5, 0xca, 0xa6, - 0xb9, 0x09, 0x56, 0xfa, 0xf8, 0x41, 0xa5, 0x90, 0x41, 0x37, 0xe0, 0x9a, 0x06, 0xdd, 0xab, 0xd4, - 0xeb, 0x4f, 0x9f, 0xd8, 0xeb, 0x3b, 0x1b, 0xf5, 0x7a, 0x21, 0xfb, 0xde, 0x6d, 0x7e, 0x5f, 0x8c, - 0xe6, 0x00, 0xd6, 0x37, 0xea, 0xb5, 0x8d, 0xdd, 0xf5, 0xed, 0xdd, 0xcd, 0xc2, 0x25, 0x34, 0x0b, - 0xf9, 0x8a, 0xfc, 0xcc, 0xac, 0xfe, 0xd1, 0x0f, 0x30, 0x4d, 0xf8, 0x29, 0x12, 0x89, 0x36, 0x61, - 0xe9, 0xb1, 0xe3, 0x76, 0x43, 0xc7, 0xed, 0x72, 0x29, 0x10, 0x73, 0x88, 0xca, 0x43, 0x26, 0x95, - 0xc8, 0x43, 0x69, 0x54, 0x54, 0xcc, 0x9d, 0xcc, 0xfd, 0x0c, 0xaa, 0xc3, 0x42, 0x9a, 0x55, 0x86, - 0x2c, 0xfd, 0x85, 0x7b, 0x9a, 0xc2, 0x29, 0x2d, 0xa5, 0xee, 0x5d, 0x8d, 0x0f, 0xd0, 0x63, 0xb8, - 0x92, 0xd8, 0x89, 0x64, 0x7f, 0x4d, 0x7b, 0xd4, 0x30, 0x72, 0x45, 0xea, 0x9f, 0x0a, 0xdd, 0xf8, - 0x3e, 0x14, 0xa0, 0xab, 0x09, 0x03, 0x62, 0x83, 0x2c, 0x1a, 0x23, 0xb1, 0xfb, 0x19, 0x64, 0xc3, - 0x42, 0xda, 0x9e, 0x26, 0x87, 0x3c, 0x64, 0xc3, 0x2b, 0x19, 0x9a, 0x23, 0x34, 0xd3, 0x54, 0xb3, - 0xa4, 0x39, 0x44, 0x6f, 0x1b, 0x69, 0x7e, 0x49, 0x4e, 0x45, 0xdd, 0xf6, 0x23, 0x8c, 0x7b, 0x95, - 0x8e, 0xfb, 0x1c, 0x07, 0x48, 0xc4, 0x74, 0x49, 0x90, 0x09, 0xf7, 0x4e, 0x06, 0xfd, 0x16, 0x4c, - 0xd3, 0x2c, 0xa3, 0x3c, 0x04, 0x61, 0x46, 0xcd, 0x3c, 0x5a, 0x12, 0x5f, 0xb4, 0xf0, 0x7e, 0x06, - 0x7d, 0x05, 0x53, 0x9b, 0x98, 0xde, 0xc1, 0xa3, 0xb7, 0x62, 0xc9, 0xf4, 0xb7, 0xbb, 0xd2, 0xd8, - 0x16, 0x1d, 0x8e, 0x1f, 0xca, 0x51, 0x0d, 0x72, 0x1c, 0x3d, 0x40, 0x56, 0x0c, 0x3f, 0x48, 0x21, - 0x30, 0x1f, 0x23, 0x40, 0xce, 0x3b, 0xa8, 0x06, 0x79, 0x19, 0x08, 0x80, 0x96, 0x0c, 0xd1, 0x07, - 0xa5, 0x62, 0xb2, 0x80, 0x3b, 0x7a, 0xc6, 0xfe, 0x6e, 0x36, 0x83, 0xee, 0x01, 0xb0, 0xb7, 0x51, - 0x74, 0x2c, 0xf1, 0x8e, 0x96, 0x12, 0x0c, 0x44, 0x9b, 0x44, 0xb7, 0x74, 0x70, 0x88, 0xcf, 0x3b, - 0x78, 0xd3, 0x6c, 0xed, 0xc0, 0x9c, 0x7c, 0xa9, 0x74, 0x7e, 0x4e, 0x98, 0xa8, 0x7d, 0x4e, 0x56, - 0x10, 0x7b, 0xe0, 0x2b, 0x23, 0xef, 0x90, 0x29, 0x16, 0x4f, 0x4e, 0x27, 0xab, 0xa6, 0xe0, 0xca, - 0x14, 0xae, 0x12, 0x37, 0x9e, 0xd4, 0x35, 0x86, 0x8b, 0xa1, 0xa4, 0xb6, 0xab, 0x47, 0xe1, 0xa1, - 0x9b, 0x4a, 0x07, 0x52, 0x83, 0x07, 0x4b, 0x6f, 0x0d, 0xa9, 0xc1, 0xe6, 0x89, 0x6a, 0x9d, 0x87, - 0x30, 0xab, 0xc5, 0x6d, 0x21, 0x11, 0x00, 0x9e, 0x16, 0x58, 0x57, 0x5a, 0x4e, 0x2f, 0xe4, 0xc7, - 0xe2, 0x07, 0x54, 0xd9, 0xc4, 0x52, 0xa6, 0x95, 0xd2, 0x52, 0xa3, 0xb1, 0x64, 0xb8, 0x25, 0x91, - 0x44, 0x23, 0x86, 0xb2, 0x01, 0xf3, 0xd2, 0x6b, 0xaf, 0xe4, 0xa1, 0x37, 0x24, 0x59, 0x33, 0xce, - 0xdc, 0x37, 0x30, 0xcf, 0xe5, 0x40, 0x23, 0x53, 0x90, 0xca, 0x85, 0xe7, 0xe3, 0x32, 0x12, 0x78, - 0x08, 0x8b, 0xf5, 0xd8, 0x78, 0x98, 0x15, 0x75, 0x4d, 0x27, 0xa1, 0xa4, 0x57, 0x33, 0xd2, 0x7a, - 0x04, 0xa8, 0xde, 0x3f, 0x3c, 0x75, 0x25, 0xb9, 0xe7, 0x2e, 0x7e, 0x81, 0x6e, 0xc4, 0x86, 0x44, - 0x80, 0xb4, 0x1a, 0xd5, 0x4e, 0x25, 0xc3, 0x88, 0xd1, 0x3e, 0x7b, 0xf1, 0xcd, 0xf2, 0xce, 0x38, - 0x3d, 0xe7, 0xd0, 0xed, 0xb8, 0xa1, 0x8b, 0x89, 0x58, 0xa8, 0x08, 0x6a, 0x91, 0x98, 0xc1, 0x6b, - 0xc6, 0x1a, 0xe8, 0x6b, 0x98, 0xdd, 0xc4, 0x61, 0x94, 0x41, 0x0e, 0x2d, 0x25, 0x72, 0xce, 0xf1, - 0x79, 0x13, 0xf7, 0xb7, 0x7a, 0xda, 0xba, 0x6d, 0x28, 0x30, 0xe5, 0xaa, 0x90, 0xb8, 0x91, 0x20, - 0xc1, 0xab, 0x38, 0xbe, 0x73, 0x1a, 0x18, 0xb9, 0x75, 0x0f, 0xc6, 0xf7, 0xdc, 0xee, 0x11, 0x12, - 0xee, 0x58, 0x25, 0x03, 0x53, 0x69, 0x5e, 0x83, 0x71, 0xd1, 0x3b, 0x84, 0x32, 0x4b, 0x9d, 0x96, - 0x4c, 0x57, 0x26, 0xf2, 0x43, 0xbf, 0x2d, 0xc3, 0x2d, 0x87, 0xa4, 0x58, 0x93, 0xfc, 0x89, 0x97, - 0x37, 0xd6, 0xd0, 0x1e, 0xe5, 0x7a, 0xb2, 0x01, 0x74, 0x2b, 0xda, 0x4f, 0x8d, 0xd9, 0xd2, 0x4a, - 0x28, 0x4e, 0xb8, 0xb1, 0x86, 0xe4, 0x43, 0xf1, 0x14, 0xa2, 0xb7, 0xb5, 0x6d, 0xff, 0x62, 0x74, - 0xbf, 0x86, 0xbc, 0x4c, 0x15, 0x26, 0xf5, 0x4d, 0x3c, 0xbf, 0x99, 0x54, 0xe0, 0xc9, 0xac, 0x62, - 0x5f, 0xb2, 0xac, 0x7e, 0x3a, 0x7e, 0x3c, 0x9b, 0x96, 0x71, 0xf2, 0x3e, 0x83, 0x69, 0x25, 0x8f, - 0x96, 0x5c, 0x2c, 0xc9, 0xdc, 0x5a, 0x25, 0xfd, 0xf7, 0x46, 0xee, 0x93, 0x4d, 0x63, 0x8a, 0x27, - 0x6e, 0x44, 0x8b, 0x11, 0x9a, 0x92, 0x8c, 0x28, 0x86, 0x82, 0xd6, 0xe8, 0x7e, 0xc7, 0x1a, 0xba, - 0xaa, 0x63, 0x98, 0x5b, 0x59, 0x03, 0x60, 0x63, 0xa6, 0x0d, 0xe9, 0xc5, 0xc6, 0x51, 0xad, 0x91, - 0xfd, 0xac, 0x7d, 0x41, 0xa4, 0xaf, 0xc5, 0x9e, 0x46, 0x91, 0x8a, 0x1a, 0x27, 0xd5, 0x51, 0x99, - 0xf0, 0xb7, 0xa1, 0x50, 0x69, 0x51, 0x2d, 0x2b, 0xf3, 0x23, 0xa1, 0x15, 0xb9, 0x82, 0xf5, 0x02, - 0x41, 0x6b, 0x31, 0x9e, 0x6e, 0x69, 0x07, 0x3b, 0x34, 0x20, 0x6c, 0x49, 0xee, 0xb5, 0xb1, 0xa2, - 0x74, 0x0c, 0x63, 0xa7, 0x36, 0x60, 0xa1, 0xe6, 0x74, 0x5b, 0xb8, 0xf3, 0x7a, 0x64, 0x3e, 0xa7, - 0xea, 0x46, 0xc9, 0x1d, 0x75, 0x35, 0x8e, 0xcf, 0xb5, 0xcd, 0x15, 0x79, 0x54, 0x94, 0x55, 0x2b, - 0x70, 0x99, 0x31, 0x31, 0x62, 0x8b, 0x09, 0xdb, 0xd4, 0xfc, 0x27, 0x30, 0xb7, 0x41, 0xd4, 0x71, - 0xbf, 0xed, 0xb2, 0xd8, 0x61, 0xa4, 0x07, 0x83, 0x1a, 0x11, 0xb7, 0x44, 0x1e, 0x3e, 0x25, 0xa9, - 0x92, 0x14, 0xf2, 0x64, 0xde, 0xaa, 0xd2, 0x82, 0x20, 0xab, 0xe6, 0x5f, 0xa2, 0x7b, 0xef, 0x91, - 0x48, 0xdc, 0x11, 0x4b, 0x95, 0xa3, 0x2a, 0x14, 0x63, 0x22, 0x9d, 0xd2, 0xdb, 0xc3, 0x2b, 0xa9, - 0xb6, 0x98, 0x0d, 0x4b, 0x86, 0x34, 0x44, 0xe8, 0x1d, 0x69, 0x16, 0x0f, 0x4b, 0x53, 0x94, 0x62, - 0xae, 0x7d, 0xa7, 0x24, 0xa3, 0x30, 0xd0, 0x1c, 0x9e, 0x9f, 0xc8, 0xc8, 0x60, 0x19, 0x1f, 0x97, - 0x9a, 0x47, 0x08, 0xbd, 0xab, 0x53, 0x1f, 0x92, 0x6b, 0xc8, 0xd8, 0xc2, 0x13, 0x2a, 0x7a, 0x51, - 0x1a, 0x1b, 0x69, 0xf4, 0xa4, 0xe5, 0x1a, 0x92, 0x46, 0x4f, 0x6a, 0x12, 0x20, 0xc6, 0xe0, 0x4d, - 0xb8, 0x1c, 0xcb, 0xe8, 0x83, 0x6e, 0xc4, 0x19, 0x3b, 0x82, 0xa1, 0x8c, 0xd0, 0x63, 0x21, 0xd8, - 0x49, 0x42, 0xe9, 0x39, 0x7e, 0x4c, 0x63, 0x64, 0xe4, 0x0e, 0xa4, 0x09, 0xa4, 0x66, 0xed, 0x41, - 0x6f, 0xa5, 0xb0, 0xf0, 0x7c, 0xac, 0x63, 0x64, 0xeb, 0x50, 0x88, 0x27, 0xbd, 0x41, 0x2b, 0x92, - 0x4b, 0xa9, 0x99, 0x7d, 0x4a, 0x65, 0x63, 0x39, 0xdf, 0x74, 0x1e, 0x46, 0x93, 0xc2, 0xee, 0xa2, - 0xe2, 0x93, 0xa2, 0x26, 0x3c, 0x49, 0x4c, 0x8a, 0x9e, 0xc7, 0x64, 0x93, 0x46, 0xf5, 0x2a, 0xd9, - 0x6b, 0x8c, 0xa7, 0xd3, 0x1b, 0x69, 0x74, 0xa2, 0x9b, 0x9e, 0xba, 0xc8, 0x0b, 0xaa, 0xf4, 0x6b, - 0x45, 0xdb, 0x37, 0x93, 0x5d, 0x2b, 0x1b, 0xcb, 0xe5, 0x48, 0x0b, 0xf1, 0x3c, 0x2e, 0x92, 0xa8, - 0x21, 0xc1, 0x8b, 0x51, 0x94, 0x1f, 0xc0, 0x82, 0x3e, 0x8b, 0x23, 0xc6, 0x6b, 0xb6, 0x75, 0x67, - 0xb5, 0xec, 0x2d, 0x48, 0xfc, 0x7a, 0x4d, 0x2c, 0x51, 0x4c, 0x82, 0xfb, 0x29, 0x59, 0x64, 0x18, - 0xf7, 0x95, 0x4c, 0x30, 0xe7, 0xe1, 0x7e, 0x5a, 0xe2, 0x18, 0xc9, 0x28, 0xa5, 0x5f, 0x62, 0xfb, - 0x8b, 0x17, 0x5c, 0x84, 0x51, 0xe7, 0xe9, 0x9a, 0x89, 0xce, 0x3a, 0xb5, 0x6e, 0xe4, 0xcf, 0x2d, - 0x5d, 0xd3, 0xd8, 0xa4, 0x49, 0x7c, 0x49, 0x1b, 0x9c, 0x2e, 0xec, 0x35, 0x98, 0x51, 0x13, 0xd1, - 0x18, 0x7b, 0x71, 0x3d, 0x49, 0x23, 0x50, 0xce, 0x5b, 0x73, 0x92, 0x0b, 0xac, 0x37, 0xcb, 0x71, - 0xe6, 0x68, 0x1d, 0x32, 0x0f, 0x09, 0xa9, 0xac, 0x19, 0xd1, 0x25, 0xb3, 0x59, 0x30, 0xcf, 0x0c, - 0x24, 0xfd, 0xd7, 0xb8, 0x0c, 0x3f, 0xea, 0x65, 0x24, 0x73, 0x40, 0xdf, 0x0a, 0xa8, 0x59, 0x65, - 0x90, 0x22, 0x25, 0x29, 0xd9, 0x66, 0x4a, 0x2b, 0xa6, 0x62, 0x55, 0x43, 0x7f, 0x0b, 0x57, 0x12, - 0xd9, 0x73, 0xa4, 0x23, 0xcc, 0x94, 0x57, 0x67, 0xb8, 0x16, 0xdc, 0x22, 0x03, 0x8e, 0x21, 0x36, - 0x56, 0x47, 0x13, 0x4d, 0xee, 0xa5, 0x3b, 0xe2, 0x79, 0x41, 0x5a, 0xe7, 0x4c, 0x39, 0x7a, 0x8c, - 0x1c, 0xdc, 0x87, 0xc5, 0xd4, 0xec, 0x3c, 0xd2, 0xac, 0x18, 0x96, 0xbb, 0xc7, 0x48, 0xf5, 0x2f, - 0xd2, 0xec, 0xb8, 0xb1, 0xcc, 0x2f, 0xd2, 0x0f, 0x61, 0xcc, 0xf6, 0x23, 0xfd, 0x10, 0xe6, 0x34, - 0x3c, 0x8c, 0x9b, 0x3b, 0xb0, 0x90, 0x96, 0x4b, 0x47, 0xf1, 0xdb, 0x19, 0x13, 0xed, 0xa4, 0x70, - 0xd4, 0x16, 0xab, 0xdd, 0x40, 0x6d, 0x48, 0x66, 0x1d, 0x23, 0x07, 0x7e, 0x26, 0xf2, 0x25, 0x25, - 0x33, 0xe0, 0xc8, 0xd3, 0xda, 0x88, 0x14, 0x39, 0x43, 0x8c, 0xca, 0xcb, 0x75, 0xf7, 0xa8, 0xab, - 0x24, 0xab, 0x91, 0x26, 0x65, 0x32, 0x4b, 0x8e, 0xd4, 0x2c, 0x69, 0xb9, 0x6d, 0x9e, 0xc0, 0x82, - 0xd8, 0x62, 0xd5, 0xe4, 0x2e, 0x28, 0x81, 0x13, 0x3d, 0x09, 0x90, 0x5a, 0x26, 0x35, 0x1b, 0x0c, - 0x3b, 0x93, 0xd1, 0x9f, 0xf3, 0x51, 0xce, 0x64, 0x4a, 0xd6, 0x95, 0x92, 0x9e, 0xa0, 0x05, 0x7d, - 0x41, 0xcf, 0x64, 0x2c, 0x09, 0x9f, 0xd9, 0x29, 0xac, 0x51, 0x8a, 0x74, 0xda, 0x9a, 0x70, 0x1b, - 0xd2, 0x06, 0x75, 0xca, 0xa3, 0x8f, 0x59, 0x14, 0x49, 0x3f, 0x66, 0xa9, 0x1d, 0x35, 0x3b, 0x67, - 0x66, 0xd4, 0x77, 0xc6, 0x92, 0x57, 0x29, 0x09, 0x09, 0x24, 0xaf, 0xd2, 0x9e, 0xf9, 0x53, 0xab, - 0x7e, 0x5f, 0x98, 0x70, 0x11, 0xbd, 0x1b, 0x43, 0xdf, 0xe9, 0x97, 0x56, 0x86, 0x3f, 0x6e, 0xe7, - 0xb7, 0x03, 0x85, 0xf8, 0x53, 0x68, 0x94, 0x96, 0x66, 0x41, 0x79, 0x0f, 0x2e, 0x0d, 0x11, 0xe3, - 0x1b, 0xea, 0x3d, 0x61, 0x1e, 0xea, 0x74, 0x0d, 0x8f, 0xed, 0x55, 0xd2, 0xc3, 0xcd, 0x88, 0xe8, - 0x55, 0xb4, 0x6a, 0xc4, 0x25, 0x5e, 0x5d, 0xab, 0x66, 0x44, 0xca, 0x43, 0x6a, 0x57, 0x84, 0xa9, - 0xa4, 0xa7, 0xee, 0x79, 0x57, 0x37, 0xb3, 0x86, 0xc4, 0xa1, 0x8e, 0xbc, 0x7f, 0x41, 0xbf, 0x23, - 0x72, 0x12, 0x26, 0x13, 0x5b, 0xbc, 0x13, 0xf3, 0xc3, 0xa4, 0x47, 0x2e, 0x96, 0x86, 0xe5, 0xcd, - 0x40, 0x8f, 0xe9, 0xeb, 0xb4, 0x27, 0xdb, 0xeb, 0x35, 0xfe, 0xa3, 0x9d, 0x9e, 0x9f, 0x70, 0x70, - 0x2b, 0x3f, 0x3c, 0x11, 0x31, 0x99, 0x55, 0xd1, 0x10, 0x1b, 0x6b, 0xa8, 0x4e, 0xfd, 0xac, 0x1a, - 0x34, 0xc5, 0xc7, 0x9d, 0x42, 0xb0, 0x94, 0x4e, 0x90, 0x3a, 0xfd, 0x37, 0xc4, 0x6e, 0xa6, 0x77, - 0xd3, 0xd0, 0x87, 0x61, 0x56, 0x00, 0x13, 0x9b, 0x74, 0x32, 0xa2, 0x77, 0xa3, 0xe4, 0x88, 0x71, - 0xac, 0x5e, 0x79, 0xbc, 0xf3, 0x4a, 0x1c, 0xd3, 0x10, 0x1b, 0xab, 0x9c, 0x63, 0x1a, 0xf4, 0x62, - 0x1c, 0x8b, 0x11, 0xd4, 0x39, 0xa6, 0x77, 0xd3, 0xd0, 0x87, 0xd1, 0x1c, 0x4b, 0x27, 0x73, 0x5e, - 0x8e, 0x7d, 0x4b, 0xf7, 0xe7, 0x4d, 0xfa, 0x56, 0xea, 0x42, 0x3c, 0x2b, 0x0a, 0x0b, 0x56, 0x47, - 0x6d, 0xac, 0xa1, 0xa7, 0x34, 0xf1, 0x62, 0x0c, 0x7e, 0x3e, 0xbe, 0x2d, 0x9b, 0x88, 0x52, 0xce, - 0x6d, 0xc3, 0x22, 0xe3, 0x5c, 0xbc, 0xbb, 0xc6, 0xbe, 0x18, 0x87, 0xbd, 0x29, 0x8c, 0x9d, 0x38, - 0xa9, 0x8b, 0xf2, 0x6f, 0x9d, 0x8a, 0xc8, 0xbe, 0x4f, 0xec, 0xd3, 0x76, 0xd2, 0x78, 0xd5, 0x89, - 0x08, 0xcf, 0xb8, 0x5e, 0xbd, 0xb1, 0x8a, 0xb6, 0xe9, 0x2c, 0xe8, 0xe0, 0x61, 0xd6, 0x7d, 0x3a, - 0x19, 0xca, 0xa4, 0x2d, 0x61, 0x10, 0xc5, 0xfa, 0x64, 0x6a, 0xdb, 0xdc, 0x29, 0x79, 0xf4, 0x39, - 0xe7, 0xe8, 0x4c, 0x2c, 0x62, 0x1b, 0x3b, 0x3b, 0x69, 0x8c, 0xe2, 0x4c, 0xfc, 0x07, 0xaf, 0xd1, - 0x4f, 0x21, 0x2f, 0x90, 0x47, 0x33, 0x24, 0x8e, 0x4d, 0x19, 0xf2, 0x35, 0x4c, 0x73, 0x86, 0xd0, - 0x1e, 0x98, 0x5a, 0x32, 0x76, 0xff, 0x2b, 0x98, 0xe6, 0x6c, 0x18, 0x3a, 0x02, 0xf3, 0xb5, 0xe2, - 0xe2, 0x26, 0x0e, 0x53, 0x7e, 0x90, 0x75, 0xd4, 0x60, 0xd2, 0x7e, 0xff, 0x15, 0x35, 0xe8, 0x2b, - 0x53, 0xd3, 0x8f, 0xe7, 0x9a, 0x48, 0x8e, 0xfc, 0xe9, 0x5e, 0x42, 0xb7, 0x6e, 0xa6, 0x3b, 0x12, - 0xdf, 0x38, 0xfa, 0x5d, 0x58, 0xa6, 0x77, 0x10, 0x17, 0xed, 0xb1, 0xf9, 0x90, 0x72, 0x2d, 0x0a, - 0x3f, 0x88, 0xff, 0x6e, 0xaf, 0x89, 0xd8, 0xa8, 0x9f, 0x0c, 0x26, 0x54, 0xeb, 0x46, 0xaa, 0xa3, - 0xb0, 0x87, 0x6c, 0x46, 0xd7, 0xe9, 0xd8, 0x2f, 0xd8, 0xdb, 0xe1, 0x9a, 0x26, 0xf6, 0x43, 0xc2, - 0xa3, 0xa2, 0x27, 0xe2, 0x3f, 0x55, 0x4c, 0xa8, 0xd4, 0x13, 0x54, 0x4c, 0xb5, 0x87, 0x6d, 0x3e, - 0x74, 0x68, 0xe7, 0xec, 0x8d, 0xf9, 0x72, 0x24, 0x2f, 0x53, 0x70, 0x20, 0xc5, 0xb6, 0xd7, 0x12, - 0x4c, 0x94, 0x66, 0xd5, 0x58, 0x87, 0x00, 0x55, 0xd8, 0x1e, 0xaf, 0xa6, 0xa2, 0x50, 0xbc, 0x88, - 0xa9, 0x39, 0x2a, 0xe2, 0x24, 0xd8, 0xd9, 0x84, 0xfe, 0xba, 0xb1, 0x72, 0x36, 0x51, 0x1e, 0xe9, - 0x97, 0xf4, 0x27, 0xf4, 0x5c, 0x85, 0xd1, 0x77, 0xf4, 0xea, 0x7d, 0x91, 0xfa, 0x4c, 0x5f, 0x3d, - 0x9b, 0xe8, 0x09, 0x05, 0xe4, 0xd9, 0x84, 0x36, 0xa8, 0x53, 0x1e, 0x7d, 0x36, 0xa1, 0x48, 0xfa, - 0xd9, 0x44, 0xed, 0xa8, 0x79, 0xe1, 0xa1, 0x64, 0x46, 0x01, 0x79, 0xee, 0x36, 0x26, 0x1b, 0x18, - 0x72, 0xa5, 0x34, 0x9f, 0x92, 0x3b, 0x46, 0xda, 0xfc, 0xe6, 0xbc, 0x32, 0x25, 0xfd, 0x7e, 0xe4, - 0x7e, 0x06, 0xed, 0xd2, 0xf4, 0xc7, 0x69, 0x3f, 0xfa, 0x6c, 0x92, 0x9f, 0xa1, 0xbf, 0x32, 0x4d, - 0xe8, 0xd5, 0xd3, 0xe9, 0x0d, 0xc5, 0x1b, 0x72, 0xac, 0xbb, 0xc6, 0x23, 0x4a, 0x2e, 0xd0, 0x45, - 0xb3, 0x88, 0x4f, 0x31, 0x1f, 0xb1, 0x19, 0xb5, 0xa0, 0xfe, 0xca, 0x32, 0xdd, 0xb2, 0xee, 0xc2, - 0x24, 0x43, 0x32, 0xee, 0x36, 0xda, 0x2f, 0x33, 0xa3, 0x0f, 0xc4, 0xc5, 0x2d, 0x41, 0xd1, 0x8a, - 0x8c, 0xfd, 0xfa, 0x00, 0xf2, 0xcc, 0xed, 0x76, 0x7e, 0x94, 0x2f, 0xc4, 0xf5, 0xee, 0xb0, 0x8e, - 0x99, 0xa3, 0x2a, 0x66, 0x55, 0x87, 0xf3, 0xc5, 0x19, 0xf9, 0x15, 0x75, 0x7d, 0x0a, 0x57, 0x83, - 0x19, 0x7f, 0x31, 0xf1, 0x2b, 0xda, 0x94, 0xa5, 0x9f, 0x52, 0xff, 0xab, 0x4c, 0xc2, 0x64, 0xea, - 0x7e, 0xf2, 0x37, 0xb8, 0xd1, 0x17, 0x30, 0xc7, 0x98, 0x2b, 0x91, 0x93, 0x95, 0x86, 0xf0, 0x6c, - 0x8e, 0xb1, 0xf9, 0x55, 0x90, 0x7f, 0x2a, 0x1c, 0xb5, 0x23, 0xbb, 0x7d, 0x1e, 0x17, 0xed, 0x68, - 0xd6, 0x99, 0xa8, 0xfc, 0x0e, 0xdd, 0x74, 0xd3, 0x33, 0x87, 0x18, 0x89, 0xdd, 0x51, 0x5c, 0xd0, - 0xc3, 0x73, 0x8e, 0x9c, 0xd0, 0xe8, 0xc0, 0xf4, 0xdf, 0x61, 0xbf, 0x3d, 0x82, 0x8a, 0x60, 0xc0, - 0x4f, 0x46, 0xd6, 0x93, 0x7e, 0x2e, 0x9e, 0x7b, 0x3b, 0xbd, 0xbd, 0x11, 0xf9, 0x43, 0x52, 0x5c, - 0x86, 0x86, 0xb4, 0x1c, 0x82, 0xa0, 0x7e, 0xed, 0x38, 0x74, 0x0c, 0xe6, 0x23, 0x5a, 0x94, 0x42, - 0xfb, 0x82, 0x93, 0x60, 0x36, 0xa3, 0x50, 0x32, 0x59, 0x89, 0xbc, 0xbb, 0xd1, 0xe1, 0xfc, 0x42, - 0xfc, 0x2d, 0x13, 0x87, 0x03, 0xe5, 0x02, 0x87, 0x87, 0xa2, 0xc6, 0x7e, 0xe2, 0xd4, 0x94, 0xea, - 0x64, 0xc8, 0xe9, 0x8c, 0x07, 0x63, 0xbe, 0x11, 0x42, 0xc9, 0xd9, 0xbe, 0x38, 0x21, 0xe9, 0x18, - 0x8e, 0x11, 0xb2, 0x86, 0x4c, 0xef, 0x68, 0xa7, 0x57, 0xd1, 0x30, 0xaf, 0x17, 0x9f, 0x50, 0x27, - 0x0a, 0xfb, 0x4b, 0x66, 0x54, 0x91, 0xdb, 0xbe, 0x31, 0xbb, 0x8b, 0x9c, 0xdd, 0x21, 0xe9, 0x58, - 0x6a, 0xd1, 0x4f, 0x96, 0x68, 0x29, 0x58, 0x6a, 0xf6, 0x8e, 0x74, 0xd7, 0xa5, 0xe5, 0x66, 0x29, - 0x81, 0x28, 0xb4, 0x77, 0xc8, 0x5a, 0x37, 0xa5, 0x0f, 0x89, 0x42, 0x97, 0x86, 0x27, 0x57, 0x91, - 0x6b, 0x7d, 0x64, 0x1e, 0x92, 0x5d, 0x58, 0x48, 0x4b, 0xfb, 0x21, 0x27, 0x6d, 0x48, 0x4e, 0x90, - 0xd4, 0xf8, 0xa8, 0x3d, 0x58, 0x4c, 0x4d, 0xbd, 0x21, 0x6f, 0x48, 0x86, 0x25, 0xe6, 0x48, 0xa5, - 0xf8, 0x1d, 0x2c, 0x19, 0xf2, 0x4c, 0x44, 0x0e, 0xc4, 0xa1, 0x79, 0x28, 0x8c, 0x02, 0xf1, 0x3d, - 0x94, 0xcc, 0x29, 0x0c, 0xd0, 0x1d, 0xdd, 0x09, 0x6a, 0x4e, 0x1c, 0x50, 0x4a, 0xcd, 0xb9, 0x82, - 0xf6, 0x69, 0x3a, 0xb8, 0xb4, 0x9c, 0x06, 0xb2, 0xdf, 0xc3, 0x73, 0x1e, 0x18, 0xe2, 0xda, 0x96, - 0x0c, 0x69, 0x0c, 0x86, 0x50, 0x3d, 0x47, 0x6f, 0x77, 0x85, 0x5e, 0xd2, 0xdf, 0xb5, 0xc7, 0x42, - 0xe4, 0x53, 0x1f, 0xbd, 0xa7, 0xf6, 0xf3, 0x21, 0xcc, 0x6a, 0x0f, 0x3c, 0xa5, 0xf8, 0xa7, 0xbd, - 0xcd, 0x95, 0xde, 0xea, 0xd4, 0x37, 0xa1, 0xd5, 0xc2, 0x2f, 0xff, 0xe7, 0x4a, 0xe6, 0x97, 0xbf, - 0x5a, 0xc9, 0xfc, 0xf7, 0x5f, 0xad, 0x64, 0xfe, 0xec, 0x57, 0x2b, 0x99, 0xc3, 0x49, 0x5a, 0x7d, - 0xed, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x1f, 0x39, 0xb9, 0xf0, 0x8e, 0x00, 0x00, + 0x48, 0x49, 0xc2, 0x33, 0xf1, 0x66, 0x93, 0xf0, 0x54, 0x01, 0x72, 0x22, 0xbf, 0xa0, 0xf5, 0x47, + 0x93, 0xb0, 0xb0, 0xe3, 0x06, 0xa1, 0x98, 0x81, 0x20, 0x52, 0xcf, 0x33, 0x02, 0xa6, 0x9c, 0x31, + 0xb8, 0x25, 0xc5, 0xe0, 0xcd, 0x58, 0xba, 0x43, 0x0d, 0x01, 0x7d, 0xa4, 0x7a, 0x7a, 0xb2, 0x4a, + 0x12, 0x84, 0x64, 0xa6, 0x3a, 0xd5, 0x05, 0xf4, 0xae, 0xe6, 0xd4, 0x62, 0x7b, 0x5f, 0x87, 0x00, + 0xd4, 0xbd, 0x8f, 0xf9, 0x85, 0xd6, 0xe2, 0x9e, 0x2e, 0xd6, 0x00, 0x53, 0x5c, 0x27, 0x58, 0x33, + 0x8b, 0xa5, 0xc3, 0xe8, 0x40, 0x3a, 0x8c, 0x26, 0xe8, 0x89, 0xf4, 0x27, 0x8a, 0xc3, 0x28, 0xce, + 0x04, 0xd5, 0x69, 0xc4, 0x9e, 0xdd, 0x76, 0x28, 0x40, 0x7d, 0x76, 0xcb, 0xaa, 0xa0, 0x7d, 0x98, + 0xdf, 0xf3, 0x71, 0x9b, 0x2e, 0xff, 0x8d, 0x1f, 0x7b, 0x3e, 0x3f, 0x06, 0x50, 0xb7, 0x23, 0xcb, + 0x08, 0xd5, 0x13, 0xc5, 0x4d, 0x2c, 0xcb, 0x55, 0x2d, 0x90, 0x82, 0x8e, 0x36, 0x60, 0xae, 0x8e, + 0x1d, 0xbf, 0x75, 0xfc, 0x08, 0xbf, 0x24, 0xca, 0x2b, 0x28, 0x4e, 0x45, 0x59, 0x34, 0x02, 0x5a, + 0x42, 0x06, 0x4a, 0x8b, 0xd4, 0xab, 0x21, 0x1d, 0x09, 0xfd, 0x14, 0x26, 0xeb, 0x9e, 0x1f, 0x56, + 0x5f, 0xc6, 0x52, 0x17, 0x32, 0x60, 0xf5, 0x9a, 0xc8, 0x24, 0x12, 0x78, 0x7e, 0xd8, 0x3c, 0x54, + 0xf9, 0xc6, 0xf1, 0xd0, 0x03, 0x62, 0x19, 0x11, 0x6b, 0x2d, 0x74, 0x3a, 0x35, 0x1a, 0xe2, 0xc0, + 0x1e, 0x4e, 0x71, 0xeb, 0x87, 0x9a, 0x78, 0xa1, 0xd3, 0x69, 0xd2, 0xbd, 0x58, 0xbf, 0xa4, 0x52, + 0xb1, 0xd0, 0x4b, 0x58, 0xd0, 0x85, 0x91, 0xe7, 0x19, 0x02, 0x2d, 0x09, 0x58, 0x5a, 0x95, 0xea, + 0x1d, 0xde, 0xcb, 0x9b, 0xf1, 0x04, 0x57, 0x89, 0xd4, 0x43, 0xa9, 0x4d, 0xbc, 0x8e, 0xb3, 0xef, + 0x4f, 0x32, 0xb0, 0x18, 0x93, 0x0f, 0x7e, 0xe8, 0x7b, 0x02, 0x79, 0x09, 0xe4, 0x2e, 0x8e, 0xa2, + 0xdc, 0x9c, 0x62, 0xca, 0x8d, 0x49, 0xa7, 0x58, 0x3c, 0xea, 0x7c, 0x45, 0x34, 0xd0, 0xfd, 0x98, + 0x5f, 0x90, 0x1d, 0x26, 0xba, 0x64, 0xa7, 0xd4, 0x25, 0x5a, 0x54, 0x43, 0x9f, 0x01, 0x28, 0xd3, + 0xc2, 0x56, 0x0d, 0x4d, 0xa5, 0x97, 0x3e, 0x23, 0x4a, 0x65, 0xeb, 0xcf, 0x26, 0xc5, 0xde, 0xc7, + 0x8f, 0x9f, 0xfb, 0xbe, 0xd3, 0x3a, 0x89, 0xc2, 0x26, 0x3f, 0x4a, 0xc6, 0x28, 0x9e, 0x67, 0x09, + 0xdf, 0xd6, 0x5e, 0x33, 0x9b, 0x13, 0xa3, 0x46, 0x0f, 0xdb, 0xc7, 0xce, 0xf1, 0xb0, 0xfd, 0x1e, + 0x4c, 0x6d, 0x77, 0x9f, 0xbb, 0xc4, 0xd2, 0x65, 0x01, 0x7b, 0xd4, 0x4e, 0x74, 0x19, 0x48, 0x65, + 0x0c, 0xaf, 0x85, 0x3e, 0x83, 0xdc, 0x96, 0x17, 0x84, 0xd4, 0xd4, 0x9b, 0x88, 0x4e, 0x13, 0x21, + 0xf5, 0x93, 0x36, 0x8f, 0x79, 0x91, 0xaa, 0x24, 0x44, 0x75, 0xf4, 0x31, 0x4c, 0x55, 0xda, 0x6d, + 0xb2, 0x0a, 0xf9, 0x0a, 0xa6, 0x59, 0x15, 0x39, 0xa6, 0xc3, 0x4a, 0xd4, 0x26, 0x79, 0x65, 0xf4, + 0xa5, 0xee, 0xb4, 0x9c, 0x8a, 0xd2, 0x3e, 0xa4, 0x67, 0x18, 0xd5, 0x1d, 0x9a, 0xef, 0x8a, 0xcb, + 0xa2, 0x5c, 0x94, 0x48, 0x83, 0x26, 0xc5, 0xd0, 0x54, 0x1f, 0xbd, 0x6b, 0xda, 0x86, 0xfc, 0x76, + 0xd7, 0x0d, 0x5d, 0x9a, 0x4a, 0x20, 0xaf, 0x6d, 0x72, 0x7b, 0x8e, 0x1f, 0xba, 0x2d, 0xb7, 0xe7, + 0x74, 0x43, 0x36, 0x5b, 0xae, 0xa8, 0xa8, 0xce, 0x96, 0xc4, 0x56, 0x93, 0x0e, 0xc1, 0x1b, 0x4b, + 0x3a, 0x94, 0x9a, 0xb7, 0x67, 0xfa, 0xd5, 0xf3, 0xf6, 0xac, 0xb1, 0xb9, 0xa4, 0x86, 0xe5, 0x4c, + 0x24, 0x88, 0xd4, 0x97, 0xa7, 0x5b, 0x90, 0xb6, 0xac, 0x88, 0x6e, 0xd2, 0xd4, 0x01, 0xb3, 0x51, + 0xec, 0xab, 0x76, 0x39, 0x9d, 0xdd, 0x5e, 0x47, 0x4d, 0x98, 0x21, 0xb5, 0xf7, 0xbc, 0x8e, 0xdb, + 0x72, 0x71, 0x50, 0x9c, 0xd3, 0x9c, 0xbf, 0xfa, 0xa2, 0xa0, 0x95, 0x5e, 0xd6, 0x71, 0xc8, 0x36, + 0x41, 0xda, 0x74, 0x8f, 0x23, 0xaa, 0x9b, 0xa0, 0x4a, 0xd0, 0xb2, 0xa1, 0x18, 0xdd, 0x20, 0xc5, + 0x56, 0xd7, 0xc7, 0xc9, 0x67, 0x08, 0x34, 0x5d, 0x5d, 0xf4, 0x0c, 0x41, 0x9d, 0xb0, 0xe8, 0x41, + 0xc2, 0x01, 0x5c, 0xb7, 0xf1, 0xa9, 0xf7, 0x1c, 0xbf, 0x59, 0xb2, 0x3f, 0x87, 0x6b, 0x3a, 0xc1, + 0x83, 0x5e, 0x9b, 0x3e, 0x6b, 0x64, 0x57, 0x55, 0xa9, 0x09, 0x2f, 0x38, 0x02, 0x4b, 0x78, 0xc1, + 0x5e, 0x51, 0x93, 0x3f, 0x55, 0x79, 0xa5, 0x65, 0x96, 0x07, 0xcb, 0x3a, 0xf1, 0x4a, 0xbb, 0xad, + 0x08, 0x2a, 0xb1, 0xa2, 0x94, 0xcf, 0x98, 0xd9, 0xa6, 0x4a, 0x34, 0xd5, 0x6c, 0xbd, 0x08, 0xa0, + 0xae, 0x25, 0xa5, 0x9e, 0x85, 0xa1, 0x1c, 0x67, 0x0f, 0x61, 0x99, 0xda, 0x66, 0x15, 0x66, 0x95, + 0x4f, 0x79, 0x0a, 0xa2, 0x4b, 0x5d, 0x69, 0x41, 0x67, 0x98, 0x8e, 0x62, 0xfd, 0xab, 0x31, 0xb8, + 0xce, 0xf9, 0xf4, 0x26, 0x27, 0x03, 0xfd, 0x00, 0xd3, 0x0a, 0xfb, 0x39, 0x3f, 0x6e, 0x8a, 0x0b, + 0x7f, 0xd3, 0x34, 0x31, 0x55, 0xd3, 0xa7, 0x80, 0x66, 0x6c, 0x26, 0x88, 0x99, 0xa9, 0xce, 0x68, + 0x07, 0xe6, 0xf4, 0x39, 0xe0, 0xc6, 0xef, 0xad, 0xd4, 0x46, 0xf4, 0xaa, 0xe2, 0x55, 0x76, 0xbb, + 0x99, 0x3a, 0x13, 0x34, 0xf5, 0xa7, 0x3e, 0xbf, 0x3f, 0xc2, 0x95, 0xc4, 0x04, 0x70, 0x5b, 0xf9, + 0x76, 0x6a, 0x83, 0x89, 0xda, 0x4c, 0x6f, 0xf8, 0x14, 0x6c, 0x6c, 0x36, 0xd9, 0x48, 0x35, 0x07, + 0x93, 0x6c, 0xd8, 0x64, 0xdd, 0xec, 0xf9, 0x38, 0xc0, 0xdd, 0x16, 0x56, 0xa3, 0x2a, 0x5e, 0x77, + 0xdd, 0xfc, 0xa7, 0x0c, 0x14, 0xd3, 0xe8, 0xd6, 0x71, 0xb7, 0x8d, 0xf6, 0xa0, 0x10, 0x6f, 0x88, + 0x9f, 0x68, 0x2c, 0x61, 0x26, 0x98, 0xbb, 0xb4, 0x75, 0xc9, 0x4e, 0x60, 0x13, 0xcd, 0xaa, 0xc0, + 0x2e, 0x18, 0xbe, 0x92, 0x44, 0x55, 0x8e, 0xc2, 0xef, 0xbd, 0x07, 0x79, 0x99, 0xcf, 0x1c, 0xe5, + 0x60, 0x7c, 0x7b, 0x77, 0x7b, 0x9f, 0xe5, 0xc7, 0xda, 0x3b, 0xd8, 0x2f, 0x64, 0x10, 0xc0, 0xe4, + 0xfa, 0xc6, 0xce, 0xc6, 0xfe, 0x46, 0x21, 0xfb, 0x5e, 0x53, 0x3d, 0x54, 0xa2, 0xeb, 0xb0, 0xb4, + 0xbe, 0xd1, 0xd8, 0xae, 0x6d, 0x34, 0xf7, 0xff, 0xd2, 0xde, 0x46, 0xf3, 0x60, 0xb7, 0xbe, 0xb7, + 0x51, 0xdb, 0x7e, 0xb0, 0xbd, 0xb1, 0x5e, 0xb8, 0x84, 0x16, 0xa0, 0xa0, 0x16, 0xee, 0x3f, 0xd9, + 0xdf, 0x2b, 0x64, 0x50, 0x11, 0x16, 0x54, 0xe8, 0xd3, 0x8d, 0x6a, 0xe5, 0x60, 0x7f, 0x6b, 0xb7, + 0x30, 0x66, 0x8d, 0xe7, 0xb2, 0x85, 0xec, 0x7b, 0x3f, 0x68, 0x27, 0x4e, 0xb4, 0x0c, 0x45, 0x5e, + 0xfd, 0xa0, 0x5e, 0xd9, 0x34, 0x37, 0xc1, 0x4a, 0x1f, 0x3f, 0xa8, 0x14, 0x32, 0xe8, 0x06, 0x5c, + 0xd3, 0xa0, 0x7b, 0x95, 0x7a, 0xfd, 0xe9, 0x13, 0x7b, 0x7d, 0x67, 0xa3, 0x5e, 0x2f, 0x64, 0xdf, + 0xbb, 0xcd, 0x2f, 0xc3, 0xd1, 0x1c, 0xc0, 0xfa, 0x46, 0xbd, 0xb6, 0xb1, 0xbb, 0xbe, 0xbd, 0xbb, + 0x59, 0xb8, 0x84, 0x66, 0x21, 0x5f, 0x91, 0x9f, 0x99, 0xd5, 0x3f, 0xfe, 0x01, 0xa6, 0x09, 0x3f, + 0xc5, 0x01, 0xad, 0x09, 0x4b, 0x8f, 0x1d, 0xb7, 0x1b, 0x3a, 0x6e, 0x97, 0x4b, 0x81, 0x98, 0x43, + 0x54, 0x1e, 0x32, 0xa9, 0x44, 0x1e, 0x4a, 0xa3, 0x42, 0x7e, 0xee, 0x64, 0xee, 0x67, 0x50, 0x1d, + 0x16, 0xd2, 0xac, 0x32, 0x64, 0xe9, 0xcf, 0xf7, 0xd3, 0x14, 0x4e, 0x69, 0x29, 0x75, 0xef, 0x6a, + 0x7c, 0x80, 0x1e, 0xc3, 0x95, 0xc4, 0x4e, 0x24, 0xfb, 0x6b, 0xda, 0xa3, 0x86, 0x91, 0x2b, 0x52, + 0xe7, 0x5b, 0xe8, 0xc6, 0xf7, 0xa1, 0x00, 0x5d, 0x4d, 0x18, 0x10, 0x1b, 0x64, 0xd1, 0x18, 0x89, + 0xdd, 0xcf, 0x20, 0x1b, 0x16, 0xd2, 0xf6, 0x34, 0x39, 0xe4, 0x21, 0x1b, 0x5e, 0xc9, 0xd0, 0x1c, + 0xa1, 0x99, 0xa6, 0x9a, 0x25, 0xcd, 0x21, 0x7a, 0xdb, 0x48, 0xf3, 0x4b, 0x72, 0x20, 0xeb, 0xb6, + 0x1f, 0x61, 0xdc, 0xab, 0x74, 0xdc, 0xe7, 0x38, 0x40, 0x22, 0x60, 0x4d, 0x82, 0x4c, 0xb8, 0x77, + 0x32, 0xe8, 0xb7, 0x60, 0x9a, 0xa6, 0x50, 0xe5, 0xf1, 0x15, 0x33, 0x6a, 0x5a, 0xd5, 0x92, 0xf8, + 0xa2, 0x85, 0xf7, 0x33, 0xe8, 0x2b, 0x98, 0xda, 0xc4, 0x34, 0xc0, 0x00, 0xbd, 0x15, 0xfb, 0xa5, + 0x80, 0xed, 0xae, 0x34, 0xb6, 0x45, 0x87, 0xe3, 0x1e, 0x07, 0x54, 0x83, 0x1c, 0x47, 0x0f, 0x90, + 0x15, 0xc3, 0x0f, 0x52, 0x08, 0xcc, 0xc7, 0x08, 0x90, 0xf3, 0x0e, 0xaa, 0x41, 0x5e, 0x46, 0x39, + 0xa0, 0x25, 0x43, 0x68, 0x45, 0xa9, 0x98, 0x2c, 0xe0, 0x5e, 0xac, 0xb1, 0xbf, 0x97, 0xcd, 0xa0, + 0x7b, 0x00, 0xec, 0xe1, 0x17, 0x1d, 0x4b, 0xbc, 0xa3, 0xa5, 0x04, 0x03, 0xd1, 0x26, 0xd1, 0x2d, + 0x1d, 0x1c, 0xe2, 0xf3, 0x0e, 0xde, 0x34, 0x5b, 0x3b, 0x30, 0x27, 0x9f, 0x61, 0x9d, 0x9f, 0x13, + 0x26, 0x6a, 0x9f, 0x93, 0x15, 0xc4, 0x5e, 0x2f, 0xcb, 0xb0, 0x42, 0x64, 0x0a, 0x34, 0x94, 0xd3, + 0xc9, 0xaa, 0x29, 0xb8, 0x32, 0x3f, 0xad, 0xc4, 0x8d, 0x67, 0xac, 0x8d, 0xe1, 0x62, 0x28, 0xa9, + 0xed, 0xea, 0x21, 0x86, 0xe8, 0xa6, 0xd2, 0x81, 0xd4, 0xc8, 0xc8, 0xd2, 0x5b, 0x43, 0x6a, 0xb0, + 0x79, 0xa2, 0x5a, 0xe7, 0x21, 0xcc, 0x6a, 0x41, 0x69, 0x48, 0x44, 0xb7, 0xa7, 0x45, 0x0d, 0x96, + 0x96, 0xd3, 0x0b, 0xf9, 0xb1, 0xf8, 0x01, 0x55, 0x36, 0xb1, 0x7c, 0x70, 0xa5, 0xb4, 0xbc, 0x6f, + 0xfc, 0x70, 0x2e, 0x32, 0x84, 0xc4, 0x50, 0x36, 0x60, 0x5e, 0x5e, 0x49, 0x28, 0x49, 0xf6, 0x0d, + 0x19, 0xe4, 0x8c, 0x33, 0xf7, 0x0d, 0xcc, 0x73, 0x39, 0xd0, 0xc8, 0x14, 0xa4, 0x72, 0xe1, 0xc9, + 0xc6, 0x8c, 0x04, 0x1e, 0xc2, 0x62, 0x3d, 0x36, 0x1e, 0x66, 0x45, 0x5d, 0xd3, 0x49, 0x28, 0xb9, + 0xe3, 0x8c, 0xb4, 0x1e, 0x01, 0xaa, 0xf7, 0x0f, 0x4f, 0x5d, 0x49, 0xee, 0xb9, 0x8b, 0x5f, 0xa0, + 0x1b, 0xb1, 0x21, 0x11, 0x20, 0xad, 0x46, 0xb5, 0x53, 0xc9, 0x30, 0x62, 0xb4, 0xcf, 0x9e, 0xb3, + 0xb3, 0xa4, 0x3a, 0x4e, 0xcf, 0x39, 0x74, 0x3b, 0x6e, 0xe8, 0x62, 0x22, 0x16, 0x2a, 0x82, 0x5a, + 0x24, 0x66, 0xf0, 0x9a, 0xb1, 0x06, 0xfa, 0x1a, 0x66, 0x37, 0x71, 0x18, 0xa5, 0xc7, 0x43, 0x4b, + 0x89, 0x84, 0x7a, 0x7c, 0xde, 0xc4, 0xe5, 0xb4, 0x9e, 0x93, 0x6f, 0x1b, 0x0a, 0x4c, 0xb9, 0x2a, + 0x24, 0x6e, 0x24, 0x48, 0xf0, 0x2a, 0x8e, 0xef, 0x9c, 0x06, 0x46, 0x6e, 0xdd, 0x83, 0xf1, 0x3d, + 0xb7, 0x7b, 0x84, 0x84, 0xaf, 0x59, 0x49, 0x2f, 0x55, 0x9a, 0xd7, 0x60, 0x5c, 0xf4, 0x0e, 0xa1, + 0xcc, 0xf2, 0xc2, 0x25, 0x73, 0xb1, 0x89, 0xe4, 0xd7, 0x6f, 0xcb, 0x58, 0xd2, 0x21, 0xf9, 0xe3, + 0x24, 0x7f, 0xe2, 0xe5, 0x8d, 0x35, 0xb4, 0x47, 0xb9, 0x9e, 0x6c, 0x00, 0xdd, 0x8a, 0xf6, 0x53, + 0x63, 0x2a, 0xb8, 0x12, 0x8a, 0x13, 0x6e, 0xac, 0x21, 0xf9, 0x0a, 0x3e, 0x85, 0xe8, 0x6d, 0x6d, + 0xdb, 0xbf, 0x18, 0xdd, 0xaf, 0x21, 0x2f, 0xf3, 0xa0, 0x49, 0x7d, 0x13, 0x4f, 0xde, 0x26, 0x15, + 0x78, 0x32, 0x65, 0xda, 0x97, 0x2c, 0x65, 0xa1, 0x8e, 0x1f, 0x4f, 0x15, 0x66, 0x9c, 0xbc, 0xcf, + 0x60, 0x5a, 0x49, 0x12, 0x26, 0x17, 0x4b, 0x32, 0x71, 0x58, 0x49, 0xff, 0x31, 0x95, 0xfb, 0x64, + 0xd3, 0x98, 0xe2, 0x59, 0x29, 0xd1, 0x62, 0x84, 0xa6, 0x64, 0x5a, 0x8a, 0xa1, 0xa0, 0x35, 0xba, + 0xdf, 0xb1, 0x86, 0xae, 0xea, 0x18, 0xe6, 0x56, 0xd6, 0x00, 0xd8, 0x98, 0x69, 0x43, 0x7a, 0xb1, + 0x71, 0x54, 0x6b, 0x64, 0x3f, 0x6b, 0x5f, 0x10, 0xe9, 0x6b, 0xb1, 0xa7, 0x51, 0xa4, 0xa2, 0xc6, + 0x49, 0x75, 0x54, 0x26, 0xfc, 0x6d, 0x28, 0x54, 0x5a, 0x54, 0xcb, 0xca, 0xe4, 0x4f, 0x68, 0x45, + 0xae, 0x60, 0xbd, 0x40, 0xd0, 0x5a, 0x8c, 0xe7, 0x92, 0xda, 0xc1, 0x0e, 0x8d, 0x76, 0x5b, 0x92, + 0x7b, 0x6d, 0xac, 0x28, 0x1d, 0xc3, 0xd8, 0xa9, 0x0d, 0x58, 0xa8, 0x39, 0xdd, 0x16, 0xee, 0xbc, + 0x1e, 0x99, 0xcf, 0xa9, 0xba, 0x51, 0x12, 0x63, 0x5d, 0x8d, 0xe3, 0x73, 0x6d, 0x73, 0x45, 0x1e, + 0x15, 0x65, 0xd5, 0x0a, 0x5c, 0x66, 0x4c, 0x8c, 0xd8, 0x62, 0xc2, 0x36, 0x35, 0xff, 0x09, 0xcc, + 0x6d, 0x10, 0x75, 0xdc, 0x6f, 0xbb, 0x2c, 0x30, 0x1a, 0xe9, 0x91, 0xae, 0x46, 0xc4, 0x2d, 0x91, + 0x64, 0x50, 0xc9, 0x18, 0x25, 0x85, 0x3c, 0x99, 0x94, 0xab, 0xb4, 0x20, 0xc8, 0xaa, 0xc9, 0xa5, + 0xe8, 0xde, 0x7b, 0x24, 0xb2, 0x92, 0xc4, 0xf2, 0x00, 0xa9, 0x0a, 0xc5, 0x98, 0x25, 0xa8, 0xf4, + 0xf6, 0xf0, 0x4a, 0xaa, 0x2d, 0x66, 0xc3, 0x92, 0x21, 0xc7, 0x12, 0x7a, 0x47, 0x9a, 0xc5, 0xc3, + 0x72, 0x30, 0xa5, 0x98, 0x6b, 0xdf, 0x29, 0x99, 0x36, 0x0c, 0x34, 0x87, 0x27, 0x5f, 0x32, 0x32, + 0x58, 0x06, 0xff, 0xa5, 0x26, 0x49, 0x42, 0xef, 0xea, 0xd4, 0x87, 0x24, 0x52, 0x32, 0xb6, 0xf0, + 0x84, 0x8a, 0x5e, 0x94, 0xa3, 0x47, 0x1a, 0x3d, 0x69, 0x89, 0x94, 0xa4, 0xd1, 0x93, 0x9a, 0xe1, + 0x88, 0x31, 0x78, 0x13, 0x2e, 0xc7, 0xd2, 0x15, 0xa1, 0x1b, 0x71, 0xc6, 0x8e, 0x60, 0x28, 0x23, + 0xf4, 0x58, 0x08, 0x76, 0x92, 0x50, 0x7a, 0x02, 0x23, 0xd3, 0x18, 0x19, 0xb9, 0x03, 0x69, 0x02, + 0xa9, 0x29, 0x89, 0xd0, 0x5b, 0x29, 0x2c, 0x3c, 0x1f, 0xeb, 0x18, 0xd9, 0x3a, 0x14, 0xe2, 0x19, + 0x7d, 0xd0, 0x8a, 0xe4, 0x52, 0x6a, 0xda, 0xa2, 0x52, 0xd9, 0x58, 0xce, 0x37, 0x9d, 0x87, 0xd1, + 0xa4, 0xb0, 0x6b, 0xb0, 0xf8, 0xa4, 0xa8, 0xd9, 0x5c, 0x12, 0x93, 0xa2, 0x27, 0x69, 0xd9, 0xa4, + 0x21, 0xcb, 0x4a, 0x6a, 0x1e, 0xe3, 0xe9, 0xf4, 0x46, 0x1a, 0x9d, 0xe8, 0xa6, 0xa7, 0x2e, 0x92, + 0x9e, 0x2a, 0xfd, 0x5a, 0xd1, 0xf6, 0xcd, 0x64, 0xd7, 0xca, 0xc6, 0x72, 0x39, 0xd2, 0x42, 0x3c, + 0x49, 0x8d, 0x24, 0x6a, 0xc8, 0x5e, 0x63, 0x14, 0xe5, 0x07, 0xb0, 0xa0, 0xcf, 0xe2, 0x88, 0xf1, + 0x9a, 0x6d, 0xdd, 0x59, 0x2d, 0x35, 0x0d, 0x12, 0xb7, 0x72, 0xb1, 0x2c, 0x38, 0x09, 0xee, 0xa7, + 0xa4, 0xc8, 0x61, 0xdc, 0x57, 0xd2, 0xdc, 0x9c, 0x87, 0xfb, 0x69, 0x59, 0x71, 0x24, 0xa3, 0x94, + 0x7e, 0x89, 0xed, 0x2f, 0x5e, 0x70, 0x11, 0x46, 0x9d, 0xa7, 0x6b, 0x26, 0x3a, 0xeb, 0xd4, 0xba, + 0x91, 0xbf, 0x25, 0x75, 0x4d, 0x63, 0x93, 0x26, 0xf1, 0x25, 0x6d, 0x70, 0xba, 0xb0, 0xd7, 0x60, + 0x46, 0xcd, 0xb2, 0x63, 0xec, 0xc5, 0xf5, 0x24, 0x8d, 0x40, 0x39, 0x6f, 0xcd, 0x49, 0x2e, 0xb0, + 0xde, 0x2c, 0xc7, 0x99, 0xa3, 0x75, 0xc8, 0x3c, 0x24, 0xa4, 0xb2, 0x66, 0x44, 0x97, 0xcc, 0x66, + 0xc1, 0x3c, 0x33, 0x90, 0xf4, 0x9f, 0x1a, 0x33, 0xfc, 0x62, 0x99, 0x91, 0xcc, 0x01, 0x7d, 0x08, + 0xa1, 0xa6, 0xcc, 0x41, 0x8a, 0x94, 0xa4, 0xa4, 0xd2, 0x29, 0xad, 0x98, 0x8a, 0x55, 0x0d, 0xfd, + 0x2d, 0x5c, 0x49, 0xa4, 0x06, 0x92, 0x8e, 0x30, 0x53, 0xd2, 0xa0, 0xe1, 0x5a, 0x70, 0x8b, 0x0c, + 0x38, 0x86, 0xd8, 0x58, 0x1d, 0x4d, 0x34, 0xb9, 0x97, 0xee, 0x88, 0xb7, 0x13, 0x69, 0x9d, 0x33, + 0x25, 0x20, 0x32, 0x72, 0x70, 0x1f, 0x16, 0x53, 0x53, 0x0f, 0x49, 0xb3, 0x62, 0x58, 0x62, 0x22, + 0x23, 0xd5, 0xbf, 0x4c, 0x53, 0xff, 0xc6, 0xd2, 0xda, 0x48, 0x3f, 0x84, 0x31, 0x95, 0x91, 0xf4, + 0x43, 0x98, 0x73, 0x0c, 0x31, 0x6e, 0xee, 0xc0, 0x42, 0x5a, 0xa2, 0x20, 0xc5, 0x6f, 0x67, 0xcc, + 0x22, 0x94, 0xc2, 0x51, 0x5b, 0xac, 0x76, 0x03, 0xb5, 0x21, 0x69, 0x83, 0x8c, 0x1c, 0xf8, 0x99, + 0x48, 0x06, 0x95, 0x4c, 0xef, 0x23, 0x4f, 0x6b, 0x23, 0xf2, 0xff, 0x0c, 0x31, 0x2a, 0x2f, 0xd7, + 0xdd, 0xa3, 0xae, 0x92, 0x89, 0x47, 0x9a, 0x94, 0xc9, 0x14, 0x40, 0x52, 0xb3, 0xa4, 0x25, 0xee, + 0x79, 0x02, 0x0b, 0x62, 0x8b, 0x55, 0x33, 0xd7, 0xa0, 0x04, 0x4e, 0xf4, 0xde, 0x41, 0x6a, 0x99, + 0xd4, 0x54, 0x37, 0xec, 0x4c, 0x46, 0x7f, 0xab, 0x48, 0x39, 0x93, 0x29, 0x29, 0x65, 0x4a, 0x7a, + 0xf6, 0x19, 0xf4, 0x05, 0x3d, 0x93, 0xb1, 0x0c, 0x83, 0x66, 0xa7, 0xb0, 0x46, 0x29, 0xd2, 0x69, + 0x6b, 0xc2, 0x6d, 0x48, 0x1b, 0xd4, 0x29, 0x8f, 0x3e, 0x66, 0x51, 0x24, 0xfd, 0x98, 0xa5, 0x76, + 0xd4, 0xec, 0x9c, 0x99, 0x51, 0x1f, 0x51, 0x4b, 0x5e, 0xa5, 0x64, 0x5b, 0x90, 0xbc, 0x4a, 0xcb, + 0x61, 0x40, 0xad, 0xfa, 0x7d, 0x61, 0xc2, 0x45, 0xf4, 0x6e, 0x0c, 0x4d, 0x42, 0x50, 0x5a, 0x19, + 0xfe, 0x72, 0x9f, 0xdf, 0x0e, 0x14, 0xe2, 0xef, 0xbc, 0x51, 0x5a, 0x0e, 0x09, 0xe5, 0xb1, 0xbb, + 0x34, 0x44, 0x8c, 0x0f, 0xc4, 0xf7, 0x84, 0x79, 0xa8, 0xd3, 0x35, 0x64, 0x12, 0x50, 0x49, 0x0f, + 0x37, 0x23, 0xa2, 0x27, 0xdf, 0xaa, 0x11, 0x97, 0x78, 0x52, 0xae, 0x9a, 0x11, 0x29, 0xaf, 0xc4, + 0x5d, 0x11, 0xa6, 0x92, 0x9e, 0x97, 0xe8, 0x5d, 0xdd, 0xcc, 0x1a, 0x12, 0x64, 0x3b, 0xf2, 0xfe, + 0x05, 0xfd, 0x8e, 0x48, 0xb8, 0x98, 0xcc, 0xda, 0xf1, 0x4e, 0xcc, 0x0f, 0x93, 0x1e, 0x96, 0x59, + 0x1a, 0x96, 0x14, 0x04, 0x3d, 0xa6, 0x4f, 0xef, 0x9e, 0x6c, 0xaf, 0xd7, 0xf8, 0x2f, 0x92, 0x7a, + 0x7e, 0xc2, 0xc1, 0xad, 0xfc, 0xaa, 0x46, 0xc4, 0x64, 0x56, 0x45, 0x43, 0x6c, 0xac, 0xa1, 0x3a, + 0xf5, 0xb3, 0x6a, 0xd0, 0x14, 0x1f, 0x77, 0x0a, 0xc1, 0x52, 0x3a, 0x41, 0xea, 0xf4, 0xdf, 0x10, + 0xbb, 0x99, 0xde, 0x4d, 0x43, 0x1f, 0x86, 0x59, 0x01, 0x4c, 0x6c, 0xd2, 0xc9, 0x88, 0xde, 0x8d, + 0x92, 0x23, 0xc6, 0xb1, 0x7a, 0xe5, 0xf1, 0xce, 0x2b, 0x71, 0x4c, 0x43, 0x6c, 0xac, 0x72, 0x8e, + 0x69, 0xd0, 0x8b, 0x71, 0x2c, 0x46, 0x50, 0xe7, 0x98, 0xde, 0x4d, 0x43, 0x1f, 0x46, 0x73, 0x2c, + 0x9d, 0xcc, 0x79, 0x39, 0xf6, 0x2d, 0xdd, 0x9f, 0x37, 0xe9, 0x43, 0xb0, 0x0b, 0xf1, 0xac, 0x28, + 0x2c, 0x58, 0x1d, 0xb5, 0xb1, 0x86, 0x9e, 0xd2, 0xac, 0x92, 0x31, 0xf8, 0xf9, 0xf8, 0xb6, 0x6c, + 0x22, 0x4a, 0x39, 0xb7, 0x0d, 0x8b, 0x8c, 0x73, 0xf1, 0xee, 0x1a, 0xfb, 0x62, 0x1c, 0xf6, 0xa6, + 0x30, 0x76, 0xe2, 0xa4, 0x2e, 0xca, 0xbf, 0x75, 0x2a, 0x22, 0xfb, 0x3e, 0xb1, 0x4f, 0xdb, 0x49, + 0xe3, 0x55, 0x27, 0x22, 0x3c, 0xe3, 0x7a, 0xf5, 0xc6, 0x2a, 0xda, 0xa6, 0xb3, 0xa0, 0x83, 0x87, + 0x59, 0xf7, 0xe9, 0x64, 0x28, 0x93, 0xb6, 0x84, 0x41, 0x14, 0xeb, 0x93, 0xa9, 0x6d, 0x73, 0xa7, + 0xe4, 0xd1, 0xe7, 0x9c, 0xa3, 0x33, 0xb1, 0x88, 0x6d, 0xec, 0xec, 0xa4, 0x31, 0x8a, 0x33, 0xf1, + 0x5f, 0xf3, 0x46, 0x3f, 0x85, 0xbc, 0x40, 0x1e, 0xcd, 0x90, 0x38, 0x36, 0x65, 0xc8, 0xd7, 0x30, + 0xcd, 0x19, 0x42, 0x7b, 0x60, 0x6a, 0xc9, 0xd8, 0xfd, 0xaf, 0x60, 0x9a, 0xb3, 0x61, 0xe8, 0x08, + 0xcc, 0xd7, 0x8a, 0x8b, 0x9b, 0x38, 0x4c, 0xf9, 0xb5, 0xd9, 0x51, 0x83, 0x49, 0xfb, 0x71, 0x5b, + 0xd4, 0xa0, 0x4f, 0x68, 0x4d, 0xbf, 0x0c, 0x6c, 0x22, 0x39, 0xf2, 0x77, 0x89, 0x09, 0xdd, 0xba, + 0x99, 0xee, 0x48, 0x7c, 0xe3, 0xe8, 0x77, 0x61, 0x99, 0xde, 0x41, 0x5c, 0xb4, 0xc7, 0xe6, 0x43, + 0xca, 0xb5, 0x28, 0xfc, 0x20, 0xfe, 0xa3, 0xc4, 0x26, 0x62, 0xa3, 0x7e, 0x0f, 0x99, 0x50, 0xad, + 0x1b, 0xa9, 0x8e, 0xc2, 0x1e, 0xb2, 0x19, 0x5d, 0xa7, 0x63, 0xbf, 0x60, 0x6f, 0x87, 0x6b, 0x9a, + 0xd8, 0xaf, 0x24, 0x8f, 0x8a, 0x9e, 0x88, 0xff, 0x0e, 0x33, 0xa1, 0x52, 0x4f, 0x50, 0x31, 0xd5, + 0x1e, 0xb6, 0xf9, 0xd0, 0xa1, 0x9d, 0xb3, 0x37, 0xe6, 0xcb, 0x91, 0xbc, 0xcc, 0x2f, 0x82, 0x14, + 0xdb, 0x5e, 0xcb, 0x9e, 0x51, 0x9a, 0x55, 0x63, 0x1d, 0x02, 0x54, 0x61, 0x7b, 0xbc, 0x9a, 0x67, + 0x43, 0xf1, 0x22, 0xa6, 0x26, 0xe0, 0x88, 0x93, 0x60, 0x67, 0x13, 0xfa, 0xd3, 0xcd, 0xca, 0xd9, + 0x44, 0xc9, 0x40, 0x50, 0xd2, 0xf3, 0x03, 0x70, 0x15, 0x46, 0x93, 0x04, 0xa8, 0xf7, 0x45, 0x6a, + 0x0e, 0x02, 0xf5, 0x6c, 0xa2, 0x67, 0x4b, 0x90, 0x67, 0x13, 0xda, 0xa0, 0x4e, 0x79, 0xf4, 0xd9, + 0x84, 0x22, 0xe9, 0x67, 0x13, 0xb5, 0xa3, 0xe6, 0x85, 0x87, 0x92, 0xe9, 0x12, 0xe4, 0xb9, 0xdb, + 0x98, 0x49, 0x61, 0xc8, 0x95, 0xd2, 0x7c, 0x4a, 0x62, 0x1c, 0x69, 0xf3, 0x9b, 0x93, 0xe6, 0x94, + 0xf4, 0xfb, 0x91, 0xfb, 0x19, 0xb4, 0x4b, 0x73, 0x3b, 0xa7, 0xfd, 0xa2, 0xb5, 0x49, 0x7e, 0x86, + 0xfe, 0x84, 0x36, 0xa1, 0x57, 0x4f, 0xa7, 0x37, 0x14, 0x6f, 0xc8, 0xb1, 0xee, 0x1a, 0x8f, 0x28, + 0xb9, 0x40, 0x17, 0xcd, 0x22, 0x3e, 0xc5, 0x7c, 0xc4, 0x66, 0xd4, 0x82, 0xfa, 0x13, 0xd2, 0x74, + 0xcb, 0xba, 0x0b, 0x93, 0x0c, 0xc9, 0xb8, 0xdb, 0x68, 0x3f, 0x3b, 0x8d, 0x3e, 0x10, 0x17, 0xb7, + 0x04, 0x45, 0x2b, 0x32, 0xf6, 0xeb, 0x03, 0xc8, 0x33, 0xb7, 0xdb, 0xf9, 0x51, 0xbe, 0x10, 0xd7, + 0xbb, 0xc3, 0x3a, 0x66, 0x8e, 0xaa, 0x98, 0x55, 0x1d, 0xce, 0x17, 0x67, 0xe4, 0x57, 0xd4, 0xf5, + 0x29, 0x5c, 0x0d, 0x66, 0xfc, 0xc5, 0xc4, 0x4f, 0x84, 0x53, 0x96, 0x7e, 0x4a, 0xfd, 0xaf, 0x32, + 0xc3, 0x94, 0xa9, 0xfb, 0xc9, 0x1f, 0x18, 0x47, 0x5f, 0xc0, 0x1c, 0x63, 0xae, 0x44, 0x4e, 0x56, + 0x1a, 0xc2, 0xb3, 0x39, 0xc6, 0xe6, 0x57, 0x41, 0xfe, 0xa9, 0x70, 0xd4, 0x8e, 0xec, 0xf6, 0x79, + 0x5c, 0xb4, 0xa3, 0x59, 0x67, 0xa2, 0xf2, 0x3b, 0x74, 0xd3, 0x4d, 0x4f, 0x8b, 0x62, 0x24, 0x76, + 0x47, 0x71, 0x41, 0x0f, 0x4f, 0xa8, 0x72, 0x42, 0xa3, 0x03, 0xd3, 0x7f, 0x64, 0xfe, 0xf6, 0x08, + 0x2a, 0x82, 0x01, 0x3f, 0x19, 0x59, 0x4f, 0xfa, 0xb9, 0x78, 0x62, 0xf1, 0xf4, 0xf6, 0x46, 0x24, + 0x47, 0x49, 0x71, 0x19, 0x1a, 0x72, 0x8e, 0x08, 0x82, 0xfa, 0xb5, 0xe3, 0xd0, 0x31, 0x98, 0x8f, + 0x68, 0x51, 0x7e, 0xf0, 0x0b, 0x4e, 0x82, 0xd9, 0x8c, 0x42, 0xc9, 0x4c, 0x2c, 0x68, 0xd8, 0x8b, + 0x2a, 0xd5, 0x21, 0x6b, 0xca, 0xe0, 0xb2, 0x29, 0x42, 0x51, 0x63, 0xbf, 0xdf, 0x6a, 0x7a, 0x8c, + 0x38, 0xe4, 0x74, 0xc6, 0x83, 0x31, 0xdf, 0x08, 0xa1, 0xe4, 0x6c, 0x5f, 0x9c, 0x90, 0x74, 0x0c, + 0xc7, 0x08, 0x59, 0x43, 0xa6, 0x77, 0xb4, 0xd3, 0xab, 0x68, 0x98, 0xd7, 0x8b, 0x4f, 0xa8, 0x13, + 0x85, 0xfd, 0x25, 0xd3, 0xc5, 0xc8, 0x6d, 0xdf, 0x98, 0xba, 0x46, 0xce, 0xee, 0x90, 0x5c, 0x33, + 0xb5, 0xe8, 0xf7, 0x58, 0xb4, 0xfc, 0x32, 0x35, 0x7b, 0x47, 0xba, 0xeb, 0xd2, 0x12, 0xcf, 0x94, + 0x40, 0x14, 0xda, 0x3b, 0x64, 0xad, 0x9b, 0x72, 0xa3, 0x44, 0xa1, 0x4b, 0xc3, 0x33, 0xc7, 0xc8, + 0xb5, 0x3e, 0x32, 0xc9, 0xca, 0x2e, 0x2c, 0xa4, 0xe5, 0x34, 0x91, 0x93, 0x36, 0x24, 0xe1, 0x49, + 0x6a, 0x7c, 0xd4, 0x1e, 0x2c, 0xa6, 0xe6, 0x15, 0x91, 0x37, 0x24, 0xc3, 0xb2, 0x8e, 0xa4, 0x52, + 0xfc, 0x0e, 0x96, 0x0c, 0x49, 0x34, 0x22, 0x07, 0xe2, 0xd0, 0x24, 0x1b, 0x46, 0x81, 0xf8, 0x1e, + 0x4a, 0xe6, 0xfc, 0x0c, 0xe8, 0x8e, 0xee, 0x04, 0x35, 0x67, 0x45, 0x28, 0xa5, 0x26, 0x94, 0x41, + 0xfb, 0x34, 0xd7, 0x5d, 0x5a, 0xc2, 0x06, 0xd9, 0xef, 0xe1, 0x09, 0x1d, 0x0c, 0x71, 0x6d, 0x4b, + 0x86, 0x1c, 0x0d, 0x43, 0xa8, 0x9e, 0xa3, 0xb7, 0xbb, 0x42, 0x2f, 0xe9, 0x8f, 0xf6, 0x63, 0x21, + 0xf2, 0xa9, 0x2f, 0xfa, 0x53, 0xfb, 0xf9, 0x10, 0x66, 0xb5, 0x07, 0x9e, 0x52, 0xfc, 0xd3, 0x9e, + 0x05, 0x4b, 0x6f, 0x75, 0xea, 0x9b, 0xd0, 0x6a, 0xe1, 0x97, 0xff, 0x73, 0x25, 0xf3, 0xcb, 0x5f, + 0xad, 0x64, 0xfe, 0xfb, 0xaf, 0x56, 0x32, 0x7f, 0xfe, 0xab, 0x95, 0xcc, 0xe1, 0x24, 0xad, 0xbe, + 0xf6, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x94, 0x74, 0xa0, 0xcd, 0x8f, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -24989,6 +25013,27 @@ func (m *PaginatedResource_KubeService) MarshalToSizedBuffer(dAtA []byte) (int, } return len(dAtA) - i, nil } +func (m *PaginatedResource_WindowsDesktop) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PaginatedResource_WindowsDesktop) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.WindowsDesktop != nil { + { + size, err := m.WindowsDesktop.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthservice(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + return len(dAtA) - i, nil +} func (m *ListResourcesRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -25013,6 +25058,16 @@ func (m *ListResourcesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + { + size, err := m.WindowsDesktopFilter.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAuthservice(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 if m.NeedTotalCount { i-- if m.NeedTotalCount { @@ -25209,12 +25264,12 @@ func (m *CreateSessionTrackerRequest) MarshalToSizedBuffer(dAtA []byte) (int, er i-- dAtA[i] = 0x5a } - n98, err98 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expires, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expires):]) - if err98 != nil { - return 0, err98 + n100, err100 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expires, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expires):]) + if err100 != nil { + return 0, err100 } - i -= n98 - i = encodeVarintAuthservice(dAtA, i, uint64(n98)) + i -= n100 + i = encodeVarintAuthservice(dAtA, i, uint64(n100)) i-- dAtA[i] = 0x52 if m.Initiator != nil { @@ -29185,6 +29240,18 @@ func (m *PaginatedResource_KubeService) Size() (n int) { } return n } +func (m *PaginatedResource_WindowsDesktop) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.WindowsDesktop != nil { + l = m.WindowsDesktop.Size() + n += 1 + l + sovAuthservice(uint64(l)) + } + return n +} func (m *ListResourcesRequest) Size() (n int) { if m == nil { return 0 @@ -29229,6 +29296,8 @@ func (m *ListResourcesRequest) Size() (n int) { if m.NeedTotalCount { n += 2 } + l = m.WindowsDesktopFilter.Size() + n += 1 + l + sovAuthservice(uint64(l)) if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -46377,6 +46446,41 @@ func (m *PaginatedResource) Unmarshal(dAtA []byte) error { } m.Resource = &PaginatedResource_KubeService{v} iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field WindowsDesktop", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthservice + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthservice + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthservice + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &types.WindowsDesktopV3{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Resource = &PaginatedResource_WindowsDesktop{v} + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipAuthservice(dAtA[iNdEx:]) @@ -46787,6 +46891,39 @@ func (m *ListResourcesRequest) Unmarshal(dAtA []byte) error { } } m.NeedTotalCount = bool(v != 0) + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field WindowsDesktopFilter", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAuthservice + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAuthservice + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAuthservice + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.WindowsDesktopFilter.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipAuthservice(dAtA[iNdEx:]) diff --git a/api/client/proto/authservice.proto b/api/client/proto/authservice.proto index be3b5c227fc11..d0a3abb2245bf 100644 --- a/api/client/proto/authservice.proto +++ b/api/client/proto/authservice.proto @@ -1457,6 +1457,9 @@ message PaginatedResource { types.ServerV2 Node = 3 [ (gogoproto.jsontag) = "node,omitempty" ]; // KubeService represents a KubernetesService resource. types.ServerV2 KubeService = 4 [ (gogoproto.jsontag) = "kube_service,omitempty" ]; + // WindowsDesktop represents a WindowsDesktop resource. + types.WindowsDesktopV3 WindowsDesktop = 5 + [ (gogoproto.jsontag) = "windows_desktop,omitempty" ]; } } @@ -1485,6 +1488,9 @@ message ListResourcesRequest { // NeedTotalCount indicates whether or not the caller also wants the total number of resources // after filtering. bool NeedTotalCount = 9 [ (gogoproto.jsontag) = "need_total_count,omitempty" ]; + // WindowsDesktopFilter specifies windows desktop specific filters. + types.WindowsDesktopFilter WindowsDesktopFilter = 10 + [ (gogoproto.nullable) = false, (gogoproto.jsontag) = "windows_desktop_filter,omitempty" ]; } // ListResourceResponse response of ListResources. diff --git a/api/types/app_test.go b/api/types/app_test.go index 731edb7ffa1a2..9b5b12d23c806 100644 --- a/api/types/app_test.go +++ b/api/types/app_test.go @@ -141,8 +141,6 @@ func TestAppServerSorter(t *testing.T) { for _, c := range cases { c := c t.Run(fmt.Sprintf("%s desc", c.name), func(t *testing.T) { - t.Parallel() - sortBy := SortBy{Field: c.fieldName, IsDesc: true} servers := AppServers(makeServers(testValsUnordered, c.fieldName)) require.NoError(t, servers.SortByCustom(sortBy)) @@ -152,8 +150,6 @@ func TestAppServerSorter(t *testing.T) { }) t.Run(fmt.Sprintf("%s asc", c.name), func(t *testing.T) { - t.Parallel() - sortBy := SortBy{Field: c.fieldName} servers := AppServers(makeServers(testValsUnordered, c.fieldName)) require.NoError(t, servers.SortByCustom(sortBy)) diff --git a/api/types/appserver.go b/api/types/appserver.go index 10fb2bdea62db..aa5a96b43d2d4 100644 --- a/api/types/appserver.go +++ b/api/types/appserver.go @@ -304,7 +304,14 @@ func (s AppServers) Len() int { return len(s) } // Less compares app servers by name and host ID. func (s AppServers) Less(i, j int) bool { - return s[i].GetName() < s[j].GetName() && s[i].GetHostID() < s[j].GetHostID() + switch { + case s[i].GetName() < s[j].GetName(): + return true + case s[i].GetName() > s[j].GetName(): + return false + default: + return s[i].GetHostID() < s[j].GetHostID() + } } // Swap swaps two app servers. diff --git a/api/types/databaseserver.go b/api/types/databaseserver.go index 4a4e6cfb0e6a4..db2637513a3cc 100644 --- a/api/types/databaseserver.go +++ b/api/types/databaseserver.go @@ -291,7 +291,14 @@ func (s DatabaseServers) Len() int { return len(s) } // Less compares database servers by name and host ID. func (s DatabaseServers) Less(i, j int) bool { - return s[i].GetName() < s[j].GetName() && s[i].GetHostID() < s[j].GetHostID() + switch { + case s[i].GetName() < s[j].GetName(): + return true + case s[i].GetName() > s[j].GetName(): + return false + default: + return s[i].GetHostID() < s[j].GetHostID() + } } // Swap swaps two database servers. diff --git a/api/types/databaseserver_test.go b/api/types/databaseserver_test.go index babd27ac9a0d7..de45c5c788df8 100644 --- a/api/types/databaseserver_test.go +++ b/api/types/databaseserver_test.go @@ -154,8 +154,6 @@ func TestDatabaseServerSorter(t *testing.T) { for _, c := range cases { c := c t.Run(fmt.Sprintf("%s desc", c.name), func(t *testing.T) { - t.Parallel() - sortBy := SortBy{Field: c.fieldName, IsDesc: true} servers := DatabaseServers(makeServers(testValsUnordered, c.fieldName)) require.NoError(t, servers.SortByCustom(sortBy)) @@ -165,8 +163,6 @@ func TestDatabaseServerSorter(t *testing.T) { }) t.Run(fmt.Sprintf("%s asc", c.name), func(t *testing.T) { - t.Parallel() - sortBy := SortBy{Field: c.fieldName} servers := DatabaseServers(makeServers(testValsUnordered, c.fieldName)) require.NoError(t, servers.SortByCustom(sortBy)) diff --git a/api/types/desktop.go b/api/types/desktop.go index 6d2199711401a..9d92176e22e68 100644 --- a/api/types/desktop.go +++ b/api/types/desktop.go @@ -17,6 +17,8 @@ limitations under the License. package types import ( + "sort" + "github.com/gravitational/teleport/api/utils" "github.com/gravitational/trace" ) @@ -218,3 +220,91 @@ func (f *WindowsDesktopFilter) Match(req WindowsDesktop) bool { } return true } + +// WindowsDesktops represents a list of windows desktops. +type WindowsDesktops []WindowsDesktop + +// Len returns the slice length. +func (s WindowsDesktops) Len() int { return len(s) } + +// Less compares desktops by name and host ID. +func (s WindowsDesktops) Less(i, j int) bool { + switch { + case s[i].GetName() < s[j].GetName(): + return true + case s[i].GetName() > s[j].GetName(): + return false + default: + return s[i].GetHostID() < s[j].GetHostID() + } +} + +// Swap swaps two windows desktops. +func (s WindowsDesktops) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// SortByCustom custom sorts by given sort criteria. +func (s WindowsDesktops) SortByCustom(sortBy SortBy) error { + if sortBy.Field == "" { + return nil + } + + isDesc := sortBy.IsDesc + switch sortBy.Field { + case ResourceMetadataName: + sort.SliceStable(s, func(i, j int) bool { + return stringCompare(s[i].GetName(), s[j].GetName(), isDesc) + }) + case ResourceSpecAddr: + sort.SliceStable(s, func(i, j int) bool { + return stringCompare(s[i].GetAddr(), s[j].GetAddr(), isDesc) + }) + default: + return trace.NotImplemented("sorting by field %q for resource %q is not supported", sortBy.Field, KindWindowsDesktop) + } + + return nil +} + +// AsResources returns windows desktops as type resources with labels. +func (s WindowsDesktops) AsResources() []ResourceWithLabels { + resources := make([]ResourceWithLabels, 0, len(s)) + for _, server := range s { + resources = append(resources, ResourceWithLabels(server)) + } + return resources +} + +// GetFieldVals returns list of select field values. +func (s WindowsDesktops) GetFieldVals(field string) ([]string, error) { + vals := make([]string, 0, len(s)) + switch field { + case ResourceMetadataName: + for _, server := range s { + vals = append(vals, server.GetName()) + } + case ResourceSpecAddr: + for _, server := range s { + vals = append(vals, server.GetAddr()) + } + default: + return nil, trace.NotImplemented("getting field %q for resource %q is not supported", field, KindWindowsDesktop) + } + + return vals, nil +} + +// ListWindowsDesktopsResponse is a response type to ListWindowsDesktops. +type ListWindowsDesktopsResponse struct { + Desktops []WindowsDesktop + NextKey string +} + +// ListWindowsDesktopsRequest is a request type to ListWindowsDesktops. +type ListWindowsDesktopsRequest struct { + WindowsDesktopFilter + Limit int + StartKey, PredicateExpression string + Labels map[string]string + SearchKeywords []string + SortBy SortBy +} diff --git a/api/types/desktop_test.go b/api/types/desktop_test.go new file mode 100644 index 0000000000000..f17c480bd0685 --- /dev/null +++ b/api/types/desktop_test.go @@ -0,0 +1,88 @@ +/* +Copyright 2022 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package types + +import ( + "fmt" + "testing" + + "github.com/gravitational/trace" + "github.com/stretchr/testify/require" +) + +func TestWindowsDesktopsSorter(t *testing.T) { + t.Parallel() + + testValsUnordered := []string{"d", "b", "a", "c"} + + makeDesktops := func(testVals []string, testField string) []WindowsDesktop { + desktops := make([]WindowsDesktop, len(testVals)) + for i := 0; i < len(testVals); i++ { + testVal := testVals[i] + var err error + desktops[i], err = NewWindowsDesktopV3( + getTestVal(testField == ResourceMetadataName, testVal), + nil, + WindowsDesktopSpecV3{ + Addr: getTestVal(testField == ResourceSpecAddr, testVal), + }) + + require.NoError(t, err) + } + return desktops + } + + cases := []struct { + name string + fieldName string + }{ + { + name: "by name", + fieldName: ResourceMetadataName, + }, + { + name: "by addr", + fieldName: ResourceSpecAddr, + }, + } + + for _, c := range cases { + c := c + t.Run(fmt.Sprintf("%s desc", c.name), func(t *testing.T) { + sortBy := SortBy{Field: c.fieldName, IsDesc: true} + servers := WindowsDesktops(makeDesktops(testValsUnordered, c.fieldName)) + require.NoError(t, servers.SortByCustom(sortBy)) + targetVals, err := servers.GetFieldVals(c.fieldName) + require.NoError(t, err) + require.IsDecreasing(t, targetVals) + }) + + t.Run(fmt.Sprintf("%s asc", c.name), func(t *testing.T) { + sortBy := SortBy{Field: c.fieldName} + servers := WindowsDesktops(makeDesktops(testValsUnordered, c.fieldName)) + require.NoError(t, servers.SortByCustom(sortBy)) + targetVals, err := servers.GetFieldVals(c.fieldName) + require.NoError(t, err) + require.IsIncreasing(t, targetVals) + }) + } + + // Test error. + sortBy := SortBy{Field: "unsupported"} + desktops := makeDesktops(testValsUnordered, "does-not-matter") + require.True(t, trace.IsNotImplemented(WindowsDesktops(desktops).SortByCustom(sortBy))) +} diff --git a/api/types/resource.go b/api/types/resource.go index ef52ae8ca0f01..f0ffd15e87c92 100644 --- a/api/types/resource.go +++ b/api/types/resource.go @@ -148,6 +148,19 @@ func (r ResourcesWithLabels) AsDatabaseServers() ([]DatabaseServer, error) { return dbs, nil } +// AsWindowsDesktops converts each resource into type WindowsDesktop. +func (r ResourcesWithLabels) AsWindowsDesktops() ([]WindowsDesktop, error) { + desktops := make([]WindowsDesktop, 0, len(r)) + for _, resource := range r { + desktop, ok := resource.(WindowsDesktop) + if !ok { + return nil, trace.BadParameter("expected types.WindowsDesktop, got: %T", resource) + } + desktops = append(desktops, desktop) + } + return desktops, nil +} + // GetVersion returns resource version func (h *ResourceHeader) GetVersion() string { return h.Version diff --git a/api/types/server_test.go b/api/types/server_test.go index b5de2617ae0e4..4b145d7bb0ad2 100644 --- a/api/types/server_test.go +++ b/api/types/server_test.go @@ -76,8 +76,6 @@ func TestServerSorter(t *testing.T) { for _, c := range cases { c := c t.Run(fmt.Sprintf("%s desc", c.name), func(t *testing.T) { - t.Parallel() - sortBy := SortBy{Field: c.fieldName, IsDesc: true} servers := Servers(makeServers(testValsUnordered, c.fieldName)) require.NoError(t, servers.SortByCustom(sortBy)) @@ -87,8 +85,6 @@ func TestServerSorter(t *testing.T) { }) t.Run(fmt.Sprintf("%s asc", c.name), func(t *testing.T) { - t.Parallel() - sortBy := SortBy{Field: c.fieldName} servers := Servers(makeServers(testValsUnordered, c.fieldName)) require.NoError(t, servers.SortByCustom(sortBy)) diff --git a/api/types/types.pb.go b/api/types/types.pb.go index b8185b731b525..ed7f846a6b52d 100644 --- a/api/types/types.pb.go +++ b/api/types/types.pb.go @@ -8195,8 +8195,11 @@ func (m *WindowsDesktopServiceSpecV3) XXX_DiscardUnknown() { var xxx_messageInfo_WindowsDesktopServiceSpecV3 proto.InternalMessageInfo +// WindowsDesktopFilter are filters to apply when searching for windows desktops. type WindowsDesktopFilter struct { - HostID string `protobuf:"bytes,1,opt,name=HostID,proto3" json:"host_id"` + // HostID is the ID of the host the Windows Desktop Service proxying the desktop. + HostID string `protobuf:"bytes,1,opt,name=HostID,proto3" json:"host_id"` + // Name is the name of the desktop. Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"name"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` diff --git a/api/types/types.proto b/api/types/types.proto index 058fa01a12616..dac72721c1936 100644 --- a/api/types/types.proto +++ b/api/types/types.proto @@ -2778,8 +2778,11 @@ message WindowsDesktopServiceSpecV3 { string TeleportVersion = 2 [ (gogoproto.jsontag) = "teleport_version" ]; } +// WindowsDesktopFilter are filters to apply when searching for windows desktops. message WindowsDesktopFilter { + // HostID is the ID of the host the Windows Desktop Service proxying the desktop. string HostID = 1 [ (gogoproto.jsontag) = "host_id" ]; + // Name is the name of the desktop. string Name = 2 [ (gogoproto.jsontag) = "name" ]; } diff --git a/go.mod b/go.mod index 6e6af0b8101b2..ae48566590025 100644 --- a/go.mod +++ b/go.mod @@ -268,4 +268,5 @@ replace ( github.com/gravitational/teleport/api => ./api github.com/siddontang/go-mysql v1.1.0 => github.com/gravitational/go-mysql v1.1.1-teleport.1 github.com/sirupsen/logrus => github.com/gravitational/logrus v1.4.4-0.20210817004754-047e20245621 + github.com/vulcand/predicate => github.com/gravitational/predicate v1.2.1 ) diff --git a/go.sum b/go.sum index 8787503ddf734..27758b1196c28 100644 --- a/go.sum +++ b/go.sum @@ -441,13 +441,13 @@ github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gravitational/configure v0.0.0-20180808141939-c3428bd84c23 h1:havbccuFO5fRj0O67oHXI7doShLig3rSIXfMrd/UnkA= github.com/gravitational/configure v0.0.0-20180808141939-c3428bd84c23/go.mod h1:XL9nebvlfNVvRzRPWdDcWootcyA0l7THiH/A+W1233g= github.com/gravitational/form v0.0.0-20151109031454-c4048f792f70 h1:To76nCJtM3DI0mdq3nGLzXqTV1wNOJByxv01+u9/BxM= @@ -466,6 +466,8 @@ github.com/gravitational/logrus v1.4.4-0.20210817004754-047e20245621 h1:ivU//THq github.com/gravitational/logrus v1.4.4-0.20210817004754-047e20245621/go.mod h1:IIxugQsS57BiOTe+8zDv3sfnvM2BQ3smcF1xJdj3Has= github.com/gravitational/oxy v0.0.0-20211213172937-a1ba0900a4c9 h1:7NyppZS8QFt28nn2QjDI44vDTJs0kTRdUS7po/AxWOY= github.com/gravitational/oxy v0.0.0-20211213172937-a1ba0900a4c9/go.mod h1:ESOxlf8BB2yG3zJ0SfZe9U6wpYu3YF3znxIICg73FYA= +github.com/gravitational/predicate v1.2.1 h1:CXgXyZ90F2x4VHzOab1bBsBlpY2l+MGvb5RX3avrJ5U= +github.com/gravitational/predicate v1.2.1/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA= github.com/gravitational/protobuf v1.3.2-0.20201123192827-2b9fcfaffcbf h1:MQ4e8XcxvZTeuOmRl7yE519vcWc2h/lyvYzsvt41cdY= github.com/gravitational/protobuf v1.3.2-0.20201123192827-2b9fcfaffcbf/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gravitational/redis/v8 v8.11.5-0.20220211010318-7af711b76a91 h1:LWtt0fv7KDZt6ykJGBXd/04sONaHIMXFzHvmUAqhG8c= @@ -497,9 +499,9 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= @@ -861,8 +863,6 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/tstranex/u2f v0.0.0-20160508205855-eb799ce68da4 h1:aR+lGR8m0zBjvDlHkHOCmdsk79ipIPeiP75GqUlywKM= github.com/tstranex/u2f v0.0.0-20160508205855-eb799ce68da4/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50= -github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= @@ -956,8 +956,8 @@ golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8 h1:kACShD3qhmr/3rLmg1yXyt+N4HcwutKyPRB93s54TIU= golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= diff --git a/lib/auth/api.go b/lib/auth/api.go index 21ae421ac4366..bda207dd233de 100644 --- a/lib/auth/api.go +++ b/lib/auth/api.go @@ -809,6 +809,8 @@ type Cache interface { // ListResources returns a paginated list of resources. ListResources(ctx context.Context, req proto.ListResourcesRequest) (*types.ListResourcesResponse, error) + // ListWindowsDesktops returns a paginated list of windows desktops. + ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error) } type NodeWrapper struct { diff --git a/lib/auth/auth.go b/lib/auth/auth.go index 02d3b5cbc67d0..580cc631b68c4 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -2715,9 +2715,31 @@ type ResourcePageFunc func(next []types.ResourceWithLabels) (stop bool, err erro // IterateResourcePages can be used to iterate over pages of resources. func (a *Server) IterateResourcePages(ctx context.Context, req proto.ListResourcesRequest, f ResourcePageFunc) (*types.ListResourcesResponse, error) { for { - resp, err := a.ListResources(ctx, req) - if err != nil { - return nil, trace.Wrap(err) + var resp *types.ListResourcesResponse + switch { + case req.ResourceType == types.KindWindowsDesktop: + wResp, err := a.ListWindowsDesktops(ctx, types.ListWindowsDesktopsRequest{ + WindowsDesktopFilter: req.WindowsDesktopFilter, + Limit: int(req.Limit), + StartKey: req.StartKey, + PredicateExpression: req.PredicateExpression, + Labels: req.Labels, + SearchKeywords: req.SearchKeywords, + SortBy: req.SortBy, + }) + if err != nil { + return nil, trace.Wrap(err) + } + resp = &types.ListResourcesResponse{ + Resources: types.WindowsDesktops(wResp.Desktops).AsResources(), + NextKey: wResp.NextKey, + } + default: + dResp, err := a.ListResources(ctx, req) + if err != nil { + return nil, trace.Wrap(err) + } + resp = dResp } stop, err := f(resp.Resources) @@ -3010,11 +3032,16 @@ func (a *Server) GetDatabase(ctx context.Context, name string) (types.Database, return a.GetCache().GetDatabase(ctx, name) } -// GetDatabases returns all database resources. +// ListResources returns paginated resources depending on the resource type.. func (a *Server) ListResources(ctx context.Context, req proto.ListResourcesRequest) (*types.ListResourcesResponse, error) { return a.GetCache().ListResources(ctx, req) } +// ListWindowsDesktops returns paginated windows desktops. +func (a *Server) ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error) { + return a.GetCache().ListWindowsDesktops(ctx, req) +} + // GetLock gets a lock by name from the auth server's cache. func (a *Server) GetLock(ctx context.Context, name string) (types.Lock, error) { return a.GetCache().GetLock(ctx, name) diff --git a/lib/auth/auth_with_roles.go b/lib/auth/auth_with_roles.go index 2396c4c8b6003..adc9075c26ef7 100644 --- a/lib/auth/auth_with_roles.go +++ b/lib/auth/auth_with_roles.go @@ -914,7 +914,7 @@ func (a *ServerWithRoles) ListResources(ctx context.Context, req proto.ListResou // https://github.com/gravitational/teleport/pull/1224 actionVerbs = []string{types.VerbList} - case types.KindDatabaseServer, types.KindAppServer, types.KindKubeService: + case types.KindDatabaseServer, types.KindAppServer, types.KindKubeService, types.KindWindowsDesktop: default: return nil, trace.NotImplemented("resource type %s does not support pagination", req.ResourceType) @@ -991,6 +991,8 @@ func (a *ServerWithRoles) checkAccessToResource(resource types.Resource) error { default: return trace.BadParameter("could not check access to server type %q", resource.GetKind()) } + case types.WindowsDesktop: + return a.checkAccessToWindowsDesktop(r) default: return trace.BadParameter("could not check access to resource type %T", r) } @@ -1041,6 +1043,18 @@ func (a *ServerWithRoles) listResourcesWithSort(ctx context.Context, req proto.L } resources = servers.AsResources() + case types.KindWindowsDesktop: + windowsdesktops, err := a.GetWindowsDesktops(ctx, req.GetWindowsDesktopFilter()) + if err != nil { + return nil, trace.Wrap(err) + } + + desktops := types.WindowsDesktops(windowsdesktops) + if err := desktops.SortByCustom(req.SortBy); err != nil { + return nil, trace.Wrap(err) + } + resources = desktops.AsResources() + default: return nil, trace.NotImplemented("resource type %q is not supported for listResourcesWithSort", req.ResourceType) } @@ -1054,6 +1068,11 @@ func (a *ServerWithRoles) listResourcesWithSort(ctx context.Context, req proto.L return resp, nil } +// ListWindowsDesktops not implemented: can only be called locally. +func (a *ServerWithRoles) ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error) { + return nil, trace.NotImplemented(notImplementedMessage) +} + // ListNodes returns a paginated list of nodes filtered by user access. // // DELETE IN 10.0.0 in favor of ListResources. diff --git a/lib/auth/auth_with_roles_test.go b/lib/auth/auth_with_roles_test.go index 2c812a80fde7c..c2dff5f50aa97 100644 --- a/lib/auth/auth_with_roles_test.go +++ b/lib/auth/auth_with_roles_test.go @@ -2162,3 +2162,136 @@ func TestListResources_NeedTotalCountFlag(t *testing.T) { require.NotEmpty(t, resp.NextKey) require.Empty(t, resp.TotalCount) } + +func TestGetAndList_WindowsDesktops(t *testing.T) { + t.Parallel() + ctx := context.Background() + srv := newTestTLSServer(t) + + // Create test desktops. + for i := 0; i < 5; i++ { + name := uuid.New().String() + desktop, err := types.NewWindowsDesktopV3(name, map[string]string{"name": name}, + types.WindowsDesktopSpecV3{Addr: "_", HostID: "_"}) + require.NoError(t, err) + require.NoError(t, srv.Auth().UpsertWindowsDesktop(ctx, desktop)) + } + + // Test all has been upserted. + testDesktops, err := srv.Auth().GetWindowsDesktops(ctx, types.WindowsDesktopFilter{}) + require.NoError(t, err) + require.Len(t, testDesktops, 5) + + testResources := types.WindowsDesktops(testDesktops).AsResources() + + // Create user, role, and client. + username := "user" + user, role, err := CreateUserAndRole(srv.Auth(), username, nil) + require.NoError(t, err) + identity := TestUser(user.GetName()) + clt, err := srv.NewClient(identity) + require.NoError(t, err) + + // Base request. + listRequest := proto.ListResourcesRequest{ + ResourceType: types.KindWindowsDesktop, + Limit: int32(len(testDesktops) + 1), + } + + // Permit user to get the first desktop. + role.SetWindowsDesktopLabels(types.Allow, types.Labels{"name": {testDesktops[0].GetName()}}) + require.NoError(t, srv.Auth().UpsertRole(ctx, role)) + + desktops, err := clt.GetWindowsDesktops(ctx, types.WindowsDesktopFilter{}) + require.NoError(t, err) + require.EqualValues(t, 1, len(desktops)) + require.Empty(t, cmp.Diff(testDesktops[0:1], desktops)) + + resp, err := clt.ListResources(ctx, listRequest) + require.NoError(t, err) + require.Len(t, resp.Resources, 1) + require.Empty(t, cmp.Diff(testResources[0:1], resp.Resources)) + require.Empty(t, resp.NextKey) + require.Empty(t, resp.TotalCount) + + // Permit user to get all desktops. + role.SetWindowsDesktopLabels(types.Allow, types.Labels{types.Wildcard: {types.Wildcard}}) + require.NoError(t, srv.Auth().UpsertRole(ctx, role)) + desktops, err = clt.GetWindowsDesktops(ctx, types.WindowsDesktopFilter{}) + require.NoError(t, err) + require.EqualValues(t, len(testDesktops), len(desktops)) + require.Empty(t, cmp.Diff(testDesktops, desktops)) + + resp, err = clt.ListResources(ctx, listRequest) + require.NoError(t, err) + require.Len(t, resp.Resources, len(testResources)) + require.Empty(t, cmp.Diff(testResources, resp.Resources)) + require.Empty(t, resp.NextKey) + require.Empty(t, resp.TotalCount) + + // Test sorting is supported. + withSort := listRequest + withSort.SortBy = types.SortBy{IsDesc: true, Field: types.ResourceMetadataName} + resp, err = clt.ListResources(ctx, withSort) + require.NoError(t, err) + require.Len(t, resp.Resources, len(testResources)) + desktops, err = types.ResourcesWithLabels(resp.Resources).AsWindowsDesktops() + require.NoError(t, err) + names, err := types.WindowsDesktops(desktops).GetFieldVals(types.ResourceMetadataName) + require.NoError(t, err) + require.IsDecreasing(t, names) + + // Filter by labels. + withLabels := listRequest + withLabels.Labels = map[string]string{"name": testDesktops[0].GetName()} + resp, err = clt.ListResources(ctx, withLabels) + require.NoError(t, err) + require.Len(t, resp.Resources, 1) + require.Empty(t, cmp.Diff(testResources[0:1], resp.Resources)) + require.Empty(t, resp.NextKey) + require.Empty(t, resp.TotalCount) + + // Test search keywords match. + withSearchKeywords := listRequest + withSearchKeywords.SearchKeywords = []string{"name", testDesktops[0].GetName()} + resp, err = clt.ListResources(ctx, withSearchKeywords) + require.NoError(t, err) + require.Len(t, resp.Resources, 1) + require.Empty(t, cmp.Diff(testResources[0:1], resp.Resources)) + + // Test predicate match. + withExpression := listRequest + withExpression.PredicateExpression = fmt.Sprintf(`labels.name == "%s"`, testDesktops[0].GetName()) + resp, err = clt.ListResources(ctx, withExpression) + require.NoError(t, err) + require.Len(t, resp.Resources, 1) + require.Empty(t, cmp.Diff(testResources[0:1], resp.Resources)) + + // Deny user to get the first desktop. + role.SetWindowsDesktopLabels(types.Deny, types.Labels{"name": {testDesktops[0].GetName()}}) + require.NoError(t, srv.Auth().UpsertRole(ctx, role)) + + desktops, err = clt.GetWindowsDesktops(ctx, types.WindowsDesktopFilter{}) + require.NoError(t, err) + require.EqualValues(t, len(testDesktops[1:]), len(desktops)) + require.Empty(t, cmp.Diff(testDesktops[1:], desktops)) + + resp, err = clt.ListResources(ctx, listRequest) + require.NoError(t, err) + require.Len(t, resp.Resources, len(testResources[1:])) + require.Empty(t, cmp.Diff(testResources[1:], resp.Resources)) + + // Deny user all desktops. + role.SetWindowsDesktopLabels(types.Deny, types.Labels{types.Wildcard: {types.Wildcard}}) + require.NoError(t, srv.Auth().UpsertRole(ctx, role)) + + desktops, err = clt.GetWindowsDesktops(ctx, types.WindowsDesktopFilter{}) + require.NoError(t, err) + require.EqualValues(t, 0, len(desktops)) + require.Empty(t, cmp.Diff([]types.WindowsDesktop{}, desktops)) + + resp, err = clt.ListResources(ctx, listRequest) + require.NoError(t, err) + require.Len(t, resp.Resources, 0) + require.Empty(t, cmp.Diff([]types.ResourceWithLabels{}, resp.Resources)) +} diff --git a/lib/auth/clt.go b/lib/auth/clt.go index 9932e960b8b0a..4904d28d48996 100644 --- a/lib/auth/clt.go +++ b/lib/auth/clt.go @@ -1548,6 +1548,11 @@ func (c *Client) DeleteAllRoles() error { return trace.NotImplemented(notImplementedMessage) } +// ListWindowsDesktops not implemented: can only be called locally. +func (c *Client) ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error) { + return nil, trace.NotImplemented(notImplementedMessage) +} + // DeleteAllUsers not implemented: can only be called locally. func (c *Client) DeleteAllUsers() error { return trace.NotImplemented(notImplementedMessage) diff --git a/lib/auth/grpcserver.go b/lib/auth/grpcserver.go index 4cbcb7cc1c4f2..873f2f28b8366 100644 --- a/lib/auth/grpcserver.go +++ b/lib/auth/grpcserver.go @@ -3723,6 +3723,13 @@ func (g *GRPCServer) ListResources(ctx context.Context, req *proto.ListResources } protoResource = &proto.PaginatedResource{Resource: &proto.PaginatedResource_KubeService{KubeService: srv}} + case types.KindWindowsDesktop: + desktop, ok := resource.(*types.WindowsDesktopV3) + if !ok { + return nil, trace.BadParameter("windows desktop has invalid type %T", resource) + } + + protoResource = &proto.PaginatedResource{Resource: &proto.PaginatedResource_WindowsDesktop{WindowsDesktop: desktop}} default: return nil, trace.NotImplemented("resource type %s doesn't support pagination", req.ResourceType) } diff --git a/lib/auth/grpcserver_test.go b/lib/auth/grpcserver_test.go index eeaef2228d51a..9b855f0c039a1 100644 --- a/lib/auth/grpcserver_test.go +++ b/lib/auth/grpcserver_test.go @@ -1956,6 +1956,18 @@ func TestListResources(t *testing.T) { return err }, }, + "WindowsDesktops": { + resourceType: types.KindWindowsDesktop, + createResource: func(name string) error { + desktop, err := types.NewWindowsDesktopV3(name, nil, + types.WindowsDesktopSpecV3{Addr: "_", HostID: "_"}) + if err != nil { + return err + } + + return clt.UpsertWindowsDesktop(ctx, desktop) + }, + }, } for name, test := range testCases { diff --git a/lib/backend/backend.go b/lib/backend/backend.go index 2b398ec95153e..21a9b844263b2 100644 --- a/lib/backend/backend.go +++ b/lib/backend/backend.go @@ -285,6 +285,8 @@ func GetPaginationKey(r types.Resource) string { return string(internalKey(resourceWithType.GetHostID(), resourceWithType.GetName())) case types.AppServer: return string(internalKey(resourceWithType.GetHostID(), resourceWithType.GetName())) + case types.WindowsDesktop: + return string(internalKey(resourceWithType.GetHostID(), resourceWithType.GetName())) default: return r.GetName() } diff --git a/lib/cache/cache.go b/lib/cache/cache.go index 91c30e3153292..6b5910d9e4ea7 100644 --- a/lib/cache/cache.go +++ b/lib/cache/cache.go @@ -1932,6 +1932,16 @@ func (c *Cache) GetWindowsDesktops(ctx context.Context, filter types.WindowsDesk return rg.windowsDesktops.GetWindowsDesktops(ctx, filter) } +// ListWindowsDesktops returns all registered Windows desktop hosts. +func (c *Cache) ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error) { + rg, err := c.read() + if err != nil { + return nil, trace.Wrap(err) + } + defer rg.Release() + return rg.windowsDesktops.ListWindowsDesktops(ctx, req) +} + // ListResources is a part of auth.Cache implementation func (c *Cache) ListResources(ctx context.Context, req proto.ListResourcesRequest) (*types.ListResourcesResponse, error) { rg, err := c.read() diff --git a/lib/services/desktop.go b/lib/services/desktop.go index a4cc25b01e340..5ef6089109d17 100644 --- a/lib/services/desktop.go +++ b/lib/services/desktop.go @@ -33,6 +33,7 @@ type WindowsDesktops interface { UpsertWindowsDesktop(ctx context.Context, desktop types.WindowsDesktop) error DeleteWindowsDesktop(ctx context.Context, hostID, name string) error DeleteAllWindowsDesktops(context.Context) error + ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error) } // MarshalWindowsDesktop marshals the WindowsDesktop resource to JSON. diff --git a/lib/services/local/desktops.go b/lib/services/local/desktops.go index 3e0f78f381fb5..1eae39b1cc566 100644 --- a/lib/services/local/desktops.go +++ b/lib/services/local/desktops.go @@ -163,6 +163,73 @@ func (s *WindowsDesktopService) DeleteAllWindowsDesktops(ctx context.Context) er return nil } +// ListWindowsDesktops returns all Windows desktops matching filter. +func (s *WindowsDesktopService) ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error) { + reqLimit := req.Limit + if reqLimit <= 0 { + return nil, trace.BadParameter("nonpositive parameter limit") + } + + keyPrefix := []string{windowsDesktopsPrefix} + rangeStart := backend.Key(append(keyPrefix, req.StartKey)...) + rangeEnd := backend.RangeEnd(backend.Key(keyPrefix...)) + filter := services.MatchResourceFilter{ + ResourceKind: types.KindWindowsDesktop, + Labels: req.Labels, + SearchKeywords: req.SearchKeywords, + PredicateExpression: req.PredicateExpression, + } + + // Get most limit+1 results to determine if there will be a next key. + maxLimit := reqLimit + 1 + var desktops []types.WindowsDesktop + if err := backend.IterateRange(ctx, s.Backend, rangeStart, rangeEnd, maxLimit, func(items []backend.Item) (stop bool, err error) { + for _, item := range items { + if len(desktops) == maxLimit { + break + } + + desktop, err := services.UnmarshalWindowsDesktop(item.Value, + services.WithResourceID(item.ID), services.WithExpires(item.Expires)) + if err != nil { + return false, trace.Wrap(err) + } + + if !req.WindowsDesktopFilter.Match(desktop) { + continue + } + + switch match, err := services.MatchResourceByFilters(desktop, filter); { + case err != nil: + return false, trace.Wrap(err) + case match: + desktops = append(desktops, desktop) + } + } + + return len(desktops) == maxLimit, nil + }); err != nil { + return nil, trace.Wrap(err) + } + + // If both HostID and Name are set in the filter only one desktop should be expected + if req.HostID != "" && req.Name != "" && len(desktops) == 0 { + return nil, trace.NotFound("windows desktop \"%s/%s\" doesn't exist", req.HostID, req.Name) + } + + var nextKey string + if len(desktops) > reqLimit { + nextKey = backend.GetPaginationKey(desktops[len(desktops)-1]) + // Truncate the last item that was used to determine next row existence. + desktops = desktops[:reqLimit] + } + + return &types.ListWindowsDesktopsResponse{ + Desktops: desktops, + NextKey: nextKey, + }, nil +} + const ( windowsDesktopsPrefix = "windowsDesktop" ) diff --git a/lib/services/local/desktops_test.go b/lib/services/local/desktops_test.go new file mode 100644 index 0000000000000..3500b8b53b73f --- /dev/null +++ b/lib/services/local/desktops_test.go @@ -0,0 +1,213 @@ +/* +Copyright 2022 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package local + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/backend" + "github.com/gravitational/teleport/lib/backend/lite" + + "github.com/jonboulle/clockwork" + "github.com/stretchr/testify/require" +) + +func TestListWindowsDesktops(t *testing.T) { + t.Parallel() + ctx := context.Background() + + liteBackend, err := lite.NewWithConfig(ctx, lite.Config{ + Path: t.TempDir(), + Clock: clockwork.NewFakeClock(), + }) + require.NoError(t, err) + + service := NewWindowsDesktopService(liteBackend) + + // Initially we expect no desktops. + out, err := service.ListWindowsDesktops(ctx, types.ListWindowsDesktopsRequest{ + Limit: 10, + }) + require.NoError(t, err) + require.Empty(t, out.Desktops) + require.Empty(t, out.NextKey) + + // Upsert some windows desktops. + + // With label. + testLabel := map[string]string{"env": "test"} + d1, err := types.NewWindowsDesktopV3("apple", testLabel, types.WindowsDesktopSpecV3{Addr: "_"}) + require.NoError(t, err) + require.NoError(t, service.CreateWindowsDesktop(ctx, d1)) + + d2, err := types.NewWindowsDesktopV3("banana", testLabel, types.WindowsDesktopSpecV3{Addr: "_"}) + require.NoError(t, err) + require.NoError(t, service.CreateWindowsDesktop(ctx, d2)) + + // Without labels. + d3, err := types.NewWindowsDesktopV3("carrot", nil, types.WindowsDesktopSpecV3{Addr: "_", HostID: "test-host-id"}) + require.NoError(t, err) + require.NoError(t, service.CreateWindowsDesktop(ctx, d3)) + + // Test fetch all. + out, err = service.ListWindowsDesktops(ctx, types.ListWindowsDesktopsRequest{ + Limit: 10, + }) + require.NoError(t, err) + require.Empty(t, out.NextKey) + require.Empty(t, cmp.Diff([]types.WindowsDesktop{d1, d2, d3}, out.Desktops, + cmpopts.IgnoreFields(types.Metadata{}, "ID"), + )) + + // Test pagination. + + // First fetch. + resp, err := service.ListWindowsDesktops(ctx, types.ListWindowsDesktopsRequest{ + Limit: 1, + }) + require.NoError(t, err) + require.Len(t, resp.Desktops, 1) + require.Equal(t, out.Desktops[0], resp.Desktops[0]) + require.Equal(t, backend.GetPaginationKey(out.Desktops[1]), resp.NextKey) + + // Middle fetch. + resp, err = service.ListWindowsDesktops(ctx, types.ListWindowsDesktopsRequest{ + Limit: 1, + StartKey: resp.NextKey, + }) + require.NoError(t, err) + require.Len(t, resp.Desktops, 1) + require.Equal(t, out.Desktops[1], resp.Desktops[0]) + require.Equal(t, backend.GetPaginationKey(out.Desktops[2]), resp.NextKey) + + // Last fetch. + resp, err = service.ListWindowsDesktops(ctx, types.ListWindowsDesktopsRequest{ + Limit: 1, + StartKey: resp.NextKey, + }) + require.NoError(t, err) + require.Len(t, resp.Desktops, 1) + require.Equal(t, out.Desktops[2], resp.Desktops[0]) + require.Empty(t, resp.NextKey) +} + +func TestListWindowsDesktops_Filters(t *testing.T) { + t.Parallel() + ctx := context.Background() + + liteBackend, err := lite.NewWithConfig(ctx, lite.Config{ + Path: t.TempDir(), + Clock: clockwork.NewFakeClock(), + }) + require.NoError(t, err) + + service := NewWindowsDesktopService(liteBackend) + + // Upsert some windows desktops. + + // With label. + testLabel := map[string]string{"env": "test"} + d1, err := types.NewWindowsDesktopV3("banana", testLabel, types.WindowsDesktopSpecV3{Addr: "_", HostID: "test-host-id"}) + require.NoError(t, err) + require.NoError(t, service.CreateWindowsDesktop(ctx, d1)) + + d2, err := types.NewWindowsDesktopV3("banana", testLabel, types.WindowsDesktopSpecV3{Addr: "_"}) + require.NoError(t, err) + require.NoError(t, service.CreateWindowsDesktop(ctx, d2)) + + // Without labels. + d3, err := types.NewWindowsDesktopV3("carrot", nil, types.WindowsDesktopSpecV3{Addr: "_", HostID: "test-host-id"}) + require.NoError(t, err) + require.NoError(t, service.CreateWindowsDesktop(ctx, d3)) + + tests := []struct { + name string + filter types.ListWindowsDesktopsRequest + wantErr bool + }{ + { + name: "NOK non-matching host id and name", + filter: types.ListWindowsDesktopsRequest{ + Limit: 10, + WindowsDesktopFilter: types.WindowsDesktopFilter{ + HostID: "no-match", + Name: "no-match", + }, + }, + wantErr: true, + }, + { + name: "NOK invalid limit", + filter: types.ListWindowsDesktopsRequest{}, + wantErr: true, + }, + { + name: "matching host id", + filter: types.ListWindowsDesktopsRequest{ + Limit: 5, + WindowsDesktopFilter: types.WindowsDesktopFilter{HostID: "test-host-id"}, + }, + }, + { + name: "matching name", + filter: types.ListWindowsDesktopsRequest{ + Limit: 5, + WindowsDesktopFilter: types.WindowsDesktopFilter{Name: "banana"}, + }, + }, + { + name: "with search", + filter: types.ListWindowsDesktopsRequest{ + Limit: 5, + SearchKeywords: []string{"env", "test"}, + }, + }, + { + name: "with labels", + filter: types.ListWindowsDesktopsRequest{ + Limit: 5, + Labels: testLabel, + }, + }, + { + name: "with predicate", + filter: types.ListWindowsDesktopsRequest{ + Limit: 5, + PredicateExpression: `labels.env == "test"`, + }, + }, + } + + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + resp, err := service.ListWindowsDesktops(ctx, tc.filter) + + if tc.wantErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Len(t, resp.Desktops, 2) + } + }) + } +} diff --git a/lib/services/matchers.go b/lib/services/matchers.go index d82a4dde30e51..28626542130f0 100644 --- a/lib/services/matchers.go +++ b/lib/services/matchers.go @@ -72,7 +72,7 @@ func MatchResourceByFilters(resource types.ResourceWithLabels, filter MatchResou // We assume when filtering for services like KubeService, AppServer, and DatabaseServer // the user is wanting to filter the contained resource ie. KubeClusters, Application, and Database. switch filter.ResourceKind { - case types.KindNode: + case types.KindNode, types.KindWindowsDesktop: specResource = resource case types.KindKubeService: diff --git a/lib/services/matchers_test.go b/lib/services/matchers_test.go index cfd225ae49b6d..8ec430a38b2c5 100644 --- a/lib/services/matchers_test.go +++ b/lib/services/matchers_test.go @@ -463,6 +463,18 @@ func TestMatchResourceByFilters(t *testing.T) { PredicateExpression: filterExpression, }, }, + { + name: "windows desktop", + resource: func() types.ResourceWithLabels { + desktop, err := types.NewWindowsDesktopV3("foo", nil, types.WindowsDesktopSpecV3{Addr: "_"}) + require.NoError(t, err) + return desktop + }, + filters: MatchResourceFilter{ + ResourceKind: types.KindWindowsDesktop, + PredicateExpression: filterExpression, + }, + }, } for _, tc := range testcases {