diff --git a/admin/db-domain.go b/admin/db-domain.go index 0d0e4c2..7f4e38c 100644 --- a/admin/db-domain.go +++ b/admin/db-domain.go @@ -35,7 +35,6 @@ import ( "bytes" "fmt" "net/http" - "strconv" "github.com/gin-gonic/gin" @@ -96,7 +95,7 @@ func newDomain(c *gin.Context) { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Something is wrong in received data: %s", err.Error())}) return } - ud.Id = 0 + ud.Id = nil ud.IdUser = user.Id ApiResponse(c, ud, storage.MainStore.CreateDomain(user, ud)) @@ -126,7 +125,7 @@ func updateUserDomain(c *gin.Context) { func deleteUserDomain(c *gin.Context) { user := c.MustGet("user").(*happydns.User) - domainid, err := strconv.ParseInt(c.Param("domain"), 10, 64) + domainid, err := happydns.NewIdentifierFromString(c.Param("domain")) if err != nil { domain, err := storage.MainStore.GetDomainByDN(user, c.Param("domain")) if err != nil { diff --git a/admin/db-provider.go b/admin/db-provider.go index e515751..8f19641 100644 --- a/admin/db-provider.go +++ b/admin/db-provider.go @@ -136,7 +136,7 @@ func newUserProvider(c *gin.Context) { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Something is wrong in received data: %s", err.Error())}) return } - us.Id = 0 + us.Id = nil src, err := storage.MainStore.CreateProvider(user.(*happydns.User), us, "") ApiResponse(c, src, err) diff --git a/admin/db-zone.go b/admin/db-zone.go index 46087f1..130d631 100644 --- a/admin/db-zone.go +++ b/admin/db-zone.go @@ -35,7 +35,6 @@ import ( "encoding/base64" "fmt" "net/http" - "strconv" "github.com/gin-gonic/gin" @@ -88,7 +87,7 @@ func newUserDomainZone(c *gin.Context) { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Something is wrong in received data: %s", err.Error())}) return } - uz.Id = 0 + uz.Id = nil ApiResponse(c, uz, storage.MainStore.CreateZone(uz)) } @@ -167,7 +166,7 @@ func patchZoneService(c *gin.Context) { } func deleteZone(c *gin.Context) { - zoneid, err := strconv.ParseInt(c.Param("zoneid"), 10, 64) + zoneid, err := happydns.NewIdentifierFromString(c.Param("zoneid")) if err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": err.Error()}) } else { diff --git a/api/domains.go b/api/domains.go index 5d654f2..3b208e7 100644 --- a/api/domains.go +++ b/api/domains.go @@ -128,7 +128,13 @@ func DomainHandler(c *gin.Context) { return } - domain, err := storage.MainStore.GetDomainByDN(user, c.Param("domain")) + dnid, err := happydns.NewIdentifierFromString(c.Param("domain")) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid domain identifier: %s", err.Error())}) + return + } + + domain, err := storage.MainStore.GetDomain(user, dnid) if err != nil { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Domain not found"}) return @@ -141,7 +147,7 @@ func DomainHandler(c *gin.Context) { } else if src, exists := c.Get("sourcemeta"); exists { source = src.(*happydns.SourceMeta) } - if source != nil && source.Id != domain.IdProvider { + if source != nil && !source.Id.Equals(domain.IdProvider) { c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "Domain not found (not child of source)"}) return } @@ -152,9 +158,9 @@ func DomainHandler(c *gin.Context) { } type apiDomain struct { - Id int64 `json:"id"` - IdUser []byte `json:"id_owner"` - IdProvider int64 `json:"id_provider"` + Id happydns.Identifier `json:"id"` + IdUser happydns.Identifier `json:"id_owner"` + IdProvider happydns.Identifier `json:"id_provider"` DomainName string `json:"domain"` ZoneHistory []happydns.ZoneMeta `json:"zone_history"` Group string `json:"group,omitempty"` @@ -194,7 +200,7 @@ func UpdateDomain(c *gin.Context) { return } - if old.Id != domain.Id { + if !old.Id.Equals(domain.Id) { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You cannot change the domain reserved ID"}) return } diff --git a/api/provider_settings.go b/api/provider_settings.go index e810c35..d608af8 100644 --- a/api/provider_settings.go +++ b/api/provider_settings.go @@ -111,7 +111,7 @@ func getProviderSettingsState(cfg *config.Options, c *gin.Context) { return } else { // Update an existing Provider - s, err := storage.MainStore.GetProvider(user, int64(uss.Id.(float64))) + s, err := storage.MainStore.GetProvider(user, uss.Id.(happydns.Identifier)) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()}) return diff --git a/api/providers.go b/api/providers.go index 8cd6c6b..530a48e 100644 --- a/api/providers.go +++ b/api/providers.go @@ -35,7 +35,6 @@ import ( "fmt" "log" "net/http" - "strconv" dnscontrol "github.com/StackExchange/dnscontrol/v3/providers" "github.com/gin-gonic/gin" @@ -110,7 +109,7 @@ func DecodeProvider(c *gin.Context) (*happydns.ProviderCombined, int, error) { func ProviderMetaHandler(c *gin.Context) { // Extract provider ID - pid, err := strconv.ParseInt(string(c.Param("pid")), 10, 64) + pid, err := happydns.NewIdentifierFromString(string(c.Param("pid"))) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid provider id: %s", err.Error())}) return @@ -138,7 +137,7 @@ func ProviderMetaHandler(c *gin.Context) { func ProviderHandler(c *gin.Context) { // Extract provider ID - pid, err := strconv.ParseInt(string(c.Param("pid")), 10, 64) + pid, err := happydns.NewIdentifierFromString(string(c.Param("pid"))) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Invalid provider id: %s", err.Error())}) return @@ -224,7 +223,7 @@ func deleteProvider(c *gin.Context) { } for _, domain := range domains { - if domain.IdProvider == providermeta.Id { + if domain.IdProvider.Equals(providermeta.Id) { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "You cannot delete this provider because there is still some domains associated with it."}) return } diff --git a/api/user_auth.go b/api/user_auth.go index ae2cea2..3555715 100644 --- a/api/user_auth.go +++ b/api/user_auth.go @@ -71,7 +71,7 @@ func declareAuthenticationRoutes(opts *config.Options, router *gin.RouterGroup) } type DisplayUser struct { - Id happydns.HexaString `json:"id"` + Id happydns.Identifier `json:"id"` Email string `json:"email"` CreatedAt time.Time `json:"created_at,omitempty"` Settings happydns.UserSettings `json:"settings,omitempty"` diff --git a/api/users.go b/api/users.go index 3234e8b..5767177 100644 --- a/api/users.go +++ b/api/users.go @@ -33,7 +33,7 @@ package api import ( "bytes" - "encoding/hex" + "encoding/base64" "fmt" "log" "net/http" @@ -356,7 +356,7 @@ func deleteUser(opts *config.Options, c *gin.Context) { } func UserHandlerBase(c *gin.Context) (*happydns.User, error) { - uid, err := hex.DecodeString(c.Param("uid")) + uid, err := base64.RawURLEncoding.DecodeString(c.Param("uid")) if err != nil { return nil, fmt.Errorf("Invalid user identifier given: %w", err) } @@ -382,7 +382,7 @@ func userHandler(c *gin.Context) { } func UserAuthHandlerBase(c *gin.Context) (*happydns.UserAuth, error) { - uid, err := hex.DecodeString(c.Param("uid")) + uid, err := base64.RawURLEncoding.DecodeString(c.Param("uid")) if err != nil { return nil, fmt.Errorf("Invalid user identifier given: %w", err) } diff --git a/api/zones.go b/api/zones.go index 4149f72..f62ce1a 100644 --- a/api/zones.go +++ b/api/zones.go @@ -32,11 +32,9 @@ package api import ( - "encoding/hex" "fmt" "log" "net/http" - "strconv" "strings" "time" @@ -78,7 +76,7 @@ func declareZonesRoutes(cfg *config.Options, router *gin.RouterGroup) { } func loadZoneFromId(domain *happydns.Domain, id string) (*happydns.Zone, int, error) { - zoneid, err := strconv.ParseInt(id, 10, 64) + zoneid, err := happydns.NewIdentifierFromString(id) if err != nil { return nil, http.StatusBadRequest, fmt.Errorf("Invalid zoneid: %q", id) } @@ -168,7 +166,7 @@ func addZoneService(c *gin.Context) { } func serviceIdHandler(c *gin.Context) { - serviceid, err := hex.DecodeString(c.Param("serviceid")) + serviceid, err := happydns.NewIdentifierFromString(c.Param("serviceid")) if err != nil { c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": fmt.Sprintf("Bad service identifier: %s", err.Error())}) return @@ -226,7 +224,7 @@ func importZone(c *gin.Context) { return } domain.ZoneHistory = append( - []int64{myZone.Id}, domain.ZoneHistory...) + []happydns.Identifier{myZone.Id}, domain.ZoneHistory...) // Create wip zone err = storage.MainStore.CreateZone(myZone) @@ -236,7 +234,7 @@ func importZone(c *gin.Context) { return } domain.ZoneHistory = append( - []int64{myZone.Id}, domain.ZoneHistory...) + []happydns.Identifier{myZone.Id}, domain.ZoneHistory...) err = storage.MainStore.UpdateDomain(domain) if err != nil { @@ -359,7 +357,7 @@ func applyZone(c *gin.Context) { } domain.ZoneHistory = append( - []int64{newZone.Id}, domain.ZoneHistory...) + []happydns.Identifier{newZone.Id}, domain.ZoneHistory...) err = storage.MainStore.UpdateDomain(domain) if err != nil { @@ -431,7 +429,7 @@ func UpdateZoneService(c *gin.Context) { func deleteZoneService(c *gin.Context) { domain := c.MustGet("domain").(*happydns.Domain) zone := c.MustGet("zone").(*happydns.Zone) - serviceid := c.MustGet("serviceid").([]byte) + serviceid := c.MustGet("serviceid").(happydns.Identifier) subdomain := c.MustGet("subdomain").(string) err := zone.EraseService(subdomain, domain.DomainName, serviceid, nil) @@ -460,7 +458,7 @@ type serviceRecord struct { func getServiceRecords(c *gin.Context) { domain := c.MustGet("domain").(*happydns.Domain) zone := c.MustGet("zone").(*happydns.Zone) - serviceid := c.MustGet("serviceid").([]byte) + serviceid := c.MustGet("serviceid").(happydns.Identifier) subdomain := c.MustGet("subdomain").(string) svc := zone.FindSubdomainService(subdomain, serviceid) diff --git a/config/user.go b/config/user.go index ef348ce..3183fde 100644 --- a/config/user.go +++ b/config/user.go @@ -32,6 +32,7 @@ package config import ( + "encoding/base64" "net/url" "git.happydns.org/happydomain/model" @@ -40,11 +41,11 @@ import ( // GetAccountRecoveryURL returns the absolute URL corresponding to the recovery // URL of the given account. func (o *Options) GetAccountRecoveryURL(u *happydns.UserAuth) string { - return o.BuildURL_noescape("/forgotten-password?u=%x&k=%s", u.Id, url.QueryEscape(u.GenAccountRecoveryHash(false))) + return o.BuildURL_noescape("/forgotten-password?u=%s&k=%s", base64.RawURLEncoding.EncodeToString(u.Id), url.QueryEscape(u.GenAccountRecoveryHash(false))) } // GetRegistrationURL returns the absolute URL corresponding to the e-mail // validation page of the given account. func (o *Options) GetRegistrationURL(u *happydns.UserAuth) string { - return o.BuildURL_noescape("/email-validation?u=%x&k=%s", u.Id, url.QueryEscape(u.GenRegistrationHash(false))) + return o.BuildURL_noescape("/email-validation?u=%s&k=%s", base64.RawURLEncoding.EncodeToString(u.Id), url.QueryEscape(u.GenRegistrationHash(false))) } diff --git a/model/domain.go b/model/domain.go index c0b3484..901b039 100644 --- a/model/domain.go +++ b/model/domain.go @@ -38,14 +38,14 @@ import ( // Domain holds information about a domain name own by a User. type Domain struct { // Id is the Domain's identifier in the database. - Id int64 `json:"id"` + Id Identifier `json:"id"` // IdUser is the identifier of the Domain's Owner. - IdUser HexaString `json:"id_owner"` + IdUser Identifier `json:"id_owner"` // IsProvider is the identifier of the Provider used to access and edit the // Domain. - IdProvider int64 `json:"id_provider"` + IdProvider Identifier `json:"id_provider"` // DomainName is the FQDN of the managed Domain. DomainName string `json:"domain"` @@ -55,7 +55,7 @@ type Domain struct { // ZoneHistory are the identifiers to the Zone attached to the current // Domain. - ZoneHistory []int64 `json:"zone_history"` + ZoneHistory []Identifier `json:"zone_history"` } // Domains is an array of Domain. @@ -63,9 +63,9 @@ type Domains []*Domain // HasZone checks if the given Zone's identifier is part of this Domain // history. -func (d *Domain) HasZone(zoneId int64) (found bool) { +func (d *Domain) HasZone(zoneId Identifier) (found bool) { for _, v := range d.ZoneHistory { - if v == zoneId { + if v.Equals(zoneId) { return true } } diff --git a/model/identifier.go b/model/identifier.go new file mode 100644 index 0000000..7b29588 --- /dev/null +++ b/model/identifier.go @@ -0,0 +1,88 @@ +// Copyright or © or Copr. happyDNS (2022) +// +// contact@happydomain.org +// +// This software is a computer program whose purpose is to provide a modern +// interface to interact with DNS systems. +// +// This software is governed by the CeCILL license under French law and abiding +// by the rules of distribution of free software. You can use, modify and/or +// redistribute the software under the terms of the CeCILL license as +// circulated by CEA, CNRS and INRIA at the following URL +// "http://www.cecill.info". +// +// As a counterpart to the access to the source code and rights to copy, modify +// and redistribute granted by the license, users are provided only with a +// limited warranty and the software's author, the holder of the economic +// rights, and the successive licensors have only limited liability. +// +// In this respect, the user's attention is drawn to the risks associated with +// loading, using, modifying and/or developing or reproducing the software by +// the user in light of its specific status of free software, that may mean +// that it is complicated to manipulate, and that also therefore means that it +// is reserved for developers and experienced professionals having in-depth +// computer knowledge. Users are therefore encouraged to load and test the +// software's suitability as regards their requirements in conditions enabling +// the security of their systems and/or data to be ensured and, more generally, +// to use and operate it in the same conditions as regards security. +// +// The fact that you are presently reading this means that you have had +// knowledge of the CeCILL license and that you accept its terms. + +package happydns + +import ( + "bytes" + "crypto/rand" + "encoding/base64" + "errors" +) + +const IDENTIFIER_LEN = 16 + +type Identifier []byte + +func NewIdentifierFromString(src string) (id Identifier, err error) { + return base64.RawURLEncoding.DecodeString(src) +} + +func NewRandomIdentifier() (id Identifier, err error) { + id = make([]byte, IDENTIFIER_LEN) + + if _, err = rand.Read(id); err != nil { + return + } + + return +} + +func (i *Identifier) IsEmpty() bool { + return len(*i) == 0 +} + +func (i Identifier) Equals(other Identifier) bool { + return bytes.Equal(i, other) +} + +func (i *Identifier) String() string { + return base64.RawURLEncoding.EncodeToString(*i) +} + +func (i Identifier) MarshalJSON() (dst []byte, err error) { + dst = make([]byte, base64.RawURLEncoding.EncodedLen(len(i))) + base64.RawURLEncoding.Encode(dst, i) + dst = append([]byte{'"'}, dst...) + dst = append(dst, '"') + return +} + +func (i *Identifier) UnmarshalJSON(src []byte) error { + if len(src) < 2 || src[0] != '"' || src[len(src)-1] != '"' { + return errors.New("Unvalid character found to encapsulate the JSON value") + } + + *i = make([]byte, base64.RawURLEncoding.DecodedLen(len(src)-2)) + _, err := base64.RawURLEncoding.Decode(*i, src[1:len(src)-1]) + + return err +} diff --git a/model/provider.go b/model/provider.go index 512c703..9a20e7b 100644 --- a/model/provider.go +++ b/model/provider.go @@ -52,10 +52,10 @@ type ProviderMeta struct { Type string `json:"_srctype"` // Id is the Provider's identifier. - Id int64 `json:"_id"` + Id Identifier `json:"_id"` // OwnerId is the User's identifier for the current Provider. - OwnerId HexaString `json:"_ownerid"` + OwnerId Identifier `json:"_ownerid"` // Comment is a string that helps user to distinguish the Provider. Comment string `json:"_comment,omitempty"` diff --git a/model/service.go b/model/service.go index 781eb80..30fdf15 100644 --- a/model/service.go +++ b/model/service.go @@ -57,10 +57,10 @@ type ServiceMeta struct { Type string `json:"_svctype"` // Id is the Service's identifier. - Id HexaString `json:"_id,omitempty"` + Id Identifier `json:"_id,omitempty"` // OwnerId is the User's identifier for the current Service. - OwnerId HexaString `json:"_ownerid,omitempty"` + OwnerId Identifier `json:"_ownerid,omitempty"` // Domain contains the abstract domain where this Service relates. Domain string `json:"_domain"` diff --git a/model/session.go b/model/session.go index 21074d3..0e8fc12 100644 --- a/model/session.go +++ b/model/session.go @@ -42,10 +42,10 @@ import ( // Session holds informatin about a User's currently connected. type Session struct { // Id is the Session's identifier. - Id []byte `json:"id"` + Id Identifier `json:"id"` // IdUser is the User's identifier of the Session. - IdUser HexaString `json:"login"` + IdUser Identifier `json:"login"` // IssuedAt holds the creation date of the Session. IssuedAt time.Time `json:"time"` diff --git a/model/source.go b/model/source.go index 2efb264..a12f85f 100644 --- a/model/source.go +++ b/model/source.go @@ -63,10 +63,10 @@ type SourceMeta struct { Type string `json:"_srctype"` // Id is the Source's identifier. - Id int64 `json:"_id"` + Id Identifier `json:"_id"` // OwnerId is the User's identifier for the current Source. - OwnerId []byte `json:"_ownerid"` + OwnerId Identifier `json:"_ownerid"` // Comment is a string that helps user to distinguish the Source. Comment string `json:"_comment,omitempty"` diff --git a/model/user.go b/model/user.go index f050900..ef42722 100644 --- a/model/user.go +++ b/model/user.go @@ -38,7 +38,7 @@ import ( // User represents an account. type User struct { // Id is the User's identifier. - Id HexaString + Id Identifier // Email is the User's login and mean of contact. Email string diff --git a/model/userauth.go b/model/userauth.go index 8d4631f..1271602 100644 --- a/model/userauth.go +++ b/model/userauth.go @@ -46,7 +46,7 @@ import ( // UserAuth represents an account used for authentication (not used in case of external auth). type UserAuth struct { // Id is the User's identifier. - Id []byte + Id Identifier // Email is the User's login and mean of contact. Email string diff --git a/model/zone.go b/model/zone.go index b0214f1..bd2caec 100644 --- a/model/zone.go +++ b/model/zone.go @@ -42,10 +42,10 @@ import ( // ZoneMeta holds the metadata associated to a Zone. type ZoneMeta struct { // Id is the Zone's identifier. - Id int64 `json:"id"` + Id Identifier `json:"id"` // IdAuthor is the User's identifier for the current Zone. - IdAuthor HexaString `json:"id_author"` + IdAuthor Identifier `json:"id_author"` // DefaultTTL is the TTL to use when no TTL has been defined for a record in this Zone. DefaultTTL uint32 `json:"default_ttl"` diff --git a/services/icons.go b/services/icons.go index 228d240..6427e39 100644 --- a/services/icons.go +++ b/services/icons.go @@ -5,5 +5,5 @@ package svcs // import "happydns.org/services" var Icons = map[string][]byte{ - "google.GSuite": []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\xc8\x00\x00\x002\b\x06\x00\x00\x00\x19Q\x94\xe1\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x14\x14IDATx\x9c\xed\x9dy\x9c\x1cU\xb5\xc7\u007f\xe7Vw\x93ej\x14\x02\x88\x90\x84 .\x80\b\x06Ġy\x12@#\x12\x10p\x99\xf0!\xb2\x88ਁ\x96\xae\xba\xd5=\x89\x1f\x81B\\\xc8tWu\xc6y\x06\x14\x05\x9e\x1aޓ\x00\x8a\b\x18\x02\t\x106\xc1\xa7\x82\x10DA\xb2\xb0ɒ\x81\xe9\t&=]\xf7\xbc?\xba\x13'3U\xdd\xd5\xeb\xcc<\xf3\xfd|\xf2G\xee\xbdu\xee\x99\xee\xbeU\xb7\xcev\tM`\xf1\xe2\xc5S\xb6n\xddz\xa0\x10b*\x11M`\xe66f\xde\n\xe0\x9f\x006k\x9a\xb6~\xf2\xe4\xc9\x1bl\xdb.4c\xfefcY\xd6ޞ\xe7\xcd\x10BLa\xe6v!D^)\xf5\x86\xa6iϧ\xd3\xe9g\x00\xf0h븋\xc6@\x8d\x10\"\xa5\xdc\x1f\xc0i\xcc<\x87\x88f\x03\xd8;\xc4e\x83\x00\x9eb\xe6{\x00\xdc=88\xb8\xb2\xb7\xb7w[#\xf4i\x06\xc9dr\xb6Rj\x01\x11\x1d\xc7\xcc\a\x97\x19\xfa\x06\x80\xdf\x11\xd1/\x84\x107vww\xe7Z\xa5c\xb3\xb0,\xeb0\xa5T\x97\x10b&3o\x03\xb0\n@\xb7\xe38\xaf\x8d\xb6nͦ\xe6\x05b\xdbv\xac\xbf\xbf\u007f\x01\x80\xf3\x89\xe8\xa3\xf5\xc8*\xb1\x99\x99\xaf\xd74\xed\xfb\xe9t\xfaou\xcaj\x18Rʹ\xcc|ii\xe1W\xcb\x00\x00W\xd7\xf5%\xb6m\xbf\xd5h\xddZ\x81a\x18\x9f\x12B\xfc\x12\xc0\x84a]\xeb5M\xfbXww\xf7\xf3\xa3\xa1W\xab\xa8\xfaGm\xdbv,\x97\xcb]\x00 \t\xe0\x9d\x8dW\t\x05\x00\xcb\x01\\\xea8Ά&\xc8\x0f\x85m\xdb\x13r\xb9\\\x06\xc0BԹ\xf8\x99y#3\x9f\x9d\xcdf\xefm\x8cv\xada\xe1\u0085m\x93&M\xfa;3\xef\x150\xe4\u05ce\xe3\x9c\xdaR\xa5Z\x8cV\xcd`)\xe5\x89\xf9|\xfeV\x00\v\x00\xe8\xcdQ\t\x02\xc0\a\x01\x9c?{\xf6\xec\u007f\xee\xb7\xdf~\x8f\xae[\xb7\xae\xa5{z)\xe5\x9e\xf9|\xfe^\x00\xa7\xa0\x01\xdbP\"z\x1b\x11\x9d9{\xf6\xec7\x1f|\xf0\xc1\xdfկak\x983g\xce\t\xcc|~\x99!\aΜ93\xfb裏\xe6[\xa6T\x8b\x11a\x06ٶ=ɲ\xace\x00n\x03\xf0\x9e檴\x836f\xceN\x9f>}e<\x1e\x0f\xba\x835\x9cx<\xdeNDw\xa0\xb8H\x1bI\x84\x99{,\xcbJ6Xn3ٳB\u007fd\u0084\t\xbb\xb7D\x93Q\"Ri@2\x99\xdc'\x97\xcb\xfd\x06\xc0\x91-\xd0Ǐ\x8fG\xa3\xd1\xdf\x1b\x861/\x9b\xcd>\xd9\xec\xc9b\xb1\xd8rf\xfeP\x85a\xcf\x02\xb8\x1b\xc0\x13(\xbe;E\x85\x10{\x018\x8a\x99?\t\xe0mA\x172\xf3\x12\xd34\u05fb\xae\xbb\xa2qZ7\a\"z\x86\xb9\xec\xc3;700\xf0r\xb9\x01\xa6i\x9eBD\xfb\fog\xe6;\\\xd7\xddT\xaf\x8eͦ\xec\x021\f\xe3\xddJ\xa9U\x00f\xb4F\x1d\u007f\x88h:\x11ݓL&\xe7\xa6\xd3\xe9?5k\x1e˲>\xc3\xcc'\x97\x19\xb2N)%\xb3\xd9\xecJ\x04\x98r-˚\f\xe0\xcb\xcc|\x19\x80v\x9f!DD\xcb\xe2\xf1\xf8=\xbd\xbd\xbd\xaf6@\xed\xa61y\xf2\xe4\ar\xb9\xdc\xff\"\xf8\xe6x\xe5\x8f~\xf4\xa3\xc1\nb,\x00\x1f\xf3i?\t\xc0\x98_ \x81[\xac\xae\xae\xae\xe9B\x88\xbb0ʋc\b\xedJ\xa9w5Q>1s\xbaL\xff\xb5\xba\xae\x1f\x99\xcdf\u007f\x8b2~\x8eL&\xb3%\x93\xc9,UJ\xcd\x04\xf0\x97\x80a{F\xa3\xd1K\xeaQ\xb6\x15ض\xad\x00|\x0e>\u007f\a\x11ݤ\xeb\xfaŭת\xb5\xf8\xbe\x80\xa6R)\xdd\xf3\xbcG\x00\x1cT\x87\xec\xe7\x01lb\xe6W\x88\xe8U\x00\xbb1s;\x11\xcd\x00\xf0^\x00\x13\xab\x90\xb5\x95\x99;\\\xd7\xfdM\x1d\xfa\x94Ų\xacY\xcc\xfc\xb0_\x1f3_\xef\xba\ue668\xd2\x01\x98L&\xf7\xf1<\xefwD4ݧ;\x97\xcf\xe7\xa7\xf6\xf6\xf6\xf6עo+\x89\xc7\xe3\xbb\xc5b\xb1\xf9\x00\x8e,9|W\xb9\xae{w\x98kMӼ\x8f\x88F\x9f\x9f\xad\x94\xfa\x0f\xd7u\xff\xd8H\xd9!x#\xa0\xfdЖj\xb1\x8b1Ŏ-\x96R\xea\x02\x84\xb3,)\":#\x93ɬk\x86B%\xab\xcehXv\xfe\n\xe0?|\xdaON$\x12\xef,m\x05w1\x86I\xa5RS\x95R\x1fUJ\xbd\x87\x88\xf6ſ~\xdf[\x88h=\x80'\xdez\xeb\xadG\x96-[6\x10V&\x01\x80mۢ\xbf\xbf\xff\xb9\x00s\xe4pz\x1c\xc7IT\xad\xfd\x18Dz\xac\xf3\x98\xf9\xc7\x01ݷ\xe9\xba~Z\xab\xf2W,\xcb:\x80\x99\x17\rog\xe6\x17]\u05fd\xacN\xd9\t\xbfp}f\xbe\xca艹L&\xf7QJ\xf9\xcd\xf9\x86\xe38]\xdb\xffc\x18\xc6\x1c!\xc4\x02\x9fq\xa7\xe0_\xef\x95C\xb9\x03e\x1c\x85\xcc\xfc\xed0\x9e\xf6x<\xde\x1e\x8bž\f\xe0\x1c\x00\x1f\xa84\x1e\xc54\x8b\xbb\x98\xf9\xda\xf6\xf6\xf6\x9bJ\xbe\x9e@\"\x00000pl\xc8\xc5\xd1\x17\x89D.\r1n\xdc\xe1y\xde/\x85\x10?\x00\xb0\x9bO\xf7I\x03\x03\x03\xb7$\x12\x89\xf3[\xf1$QJ\xbd\x83\x88Flw\x89\xe8I\x00u-\x10f\x9e\a`\xae\x8f\xec\x95\x00F,\x10\xa5\xd4\xdb\xe1\xbf\xf5~\x01\xc0\x8e\x05BD\x87\x04\x8c\v\xe2\xc4r\x9d\x9a\xa6]\x892\vȶmQ\x8a*\xbf\f@5\xf1`Q\x00'\x12щ\xb9\\\xee/\x96e\xc53\x99\xcc]A\x83\x05\x00(\xa5>\x19R\xf8\x0f\x96,Y\xf2f\x15ʌ\x1b\xb2\xd9\xecf\"\xba.\xa8\x9f\x99\xe7i\x9a\xb6NJ\xf9\xcdT*լH\xe6]\x84@J\xb9g.\x97[\x05\xe0\xfb\xa8nq\f\xe7 f\xbeӲ\xactGG\x87od\xbb\x00\x00\":>\x840\xf6<\xef'u(3\x1e\xb8\x04\xc0\xebe\xfa\xdf\x0e\xe0r\xcf\xf36\x98\xa6\xd9cY\xd6a-\xd2k\x17%\xba\xba\xba\xa6\x03x\x18@\x98\xdfl\x18\x88\x99\xad\xe9ӧ_\xdf\xd9\xd9\x19\x1d\xde)J+'\xcc\x17\xfd\x87\xa5K\x97\xaeo\x90Rc\x92L&\xf3Ji\x1f\xedU\x18\xba;\x11}\x9d\x99\x1f\x93R>b\x9a\xe6W\xe2\xf1\xb8_`\xe2.\x1aH<\x1e߫P(\xac\x06p`\x85\xa1\x1e\x8a[\xc0\xc7Q\x8c\xbc\x0e\x93\xf6<_\xd7\xf5\xff\x1c\xde(f̘1\x03\xfe\xfb\xee\x9d`\xe6\xb5!&\x19\xf7\xa4\xd3\xe9;\x99\xf9\v(\xbe̅\xe1(\"\xba*\x1a\x8d\xbe$\xa5\xbcNJy\f\x1a\x94\xeb?\xce\xd8\x06\xa0\xcf\xe7_\xd0\xe78\x100\xbe\x0f@_\xa1P\xd8\xe9&\xd5\xd1ѡ\xc5b\xb1\x1bQ~q\xdc\xcf\xcc\xf3\xa3\xd1\xe8^\x8e\xe3Lu\x1c\xe7p\xc7q\xde\xed8N\xbb\xa6i\a\x11Q\x1cEke\x10\x9dRʳ\x866D\xc2F\xc8\n!j6\xebZ\x96u,3\a\x85r\xd4\xcb_\x1a\x1d\x8a\xe2\xba\xee/L\xd3|\x85\x88~\x8e`\x0f\xfbN\x10\xd1$\x14-)\xe7H)\x9f!\xa2k<\xcf\xfba6\x9b\xdd\xdcH\xdd\xc6*\xae\xeb^\x03\xe0\x9a\xe1\xed\xa6i\xae$\xa2\x11\xef\xb8\xcc|z5\xc1\x8a\xfb\xef\xbf\u007f\x8a\x99\x8f\t\xe8\xce1\xf3\x85\xae\xeb\xfe4\xe8\xfa\xee\xee\xee\xa7\x01\"\xfaY=9%\xba\xae\xf7\x10\xd1S>]S\xa2\xd1\xe8\xc9@q۰%\x8c0\xa5T\xa8'M\xab!\xa2I~\xe6\xb9fPz\xa28\x8e\xe3\x1c\xa6\x94:\x94\x99\x97\x00\xf8G\xd8\xeb\x89\xe83\x83\x83\x83\xab[Y\x84b\xbcS(\x14\xe6\xc1?_H)\xa5\xbeS\x8fl۶\v\xcc\xec\xeb\xba \xa2y@\xf1\t\x12\xaa\xf2\x9f\xa6i\xd3\xeaQ\xa6\x99\xf4\xf5\xf5\xd5\x1dq[-\xd9l\xf6I\xd7u\x17\xe5r\xb9iDt\n\x11݄\x10[0\":\"\x16\x8b\xad\xb6m;(zx\x17C \"_\x8f;3?T.)/,B\x88\xa0\x1c\xa6c\x00 \"\x84X\x1fFP\x85r\x9b\xa3I~Ŋ\x15\x95\xfc\x16M\xa3T\xb4\xe0V\x00\xb7\x96Rl\xbfND_Cѩ\x18ġ\xb9\\.\r\xe0\x82\x96(9\x8e!\xa2\x0f\xfbUV\x11B\x14,\xcb\xea\xf2\xb9\xa4*\x989(@\xf7\xc0T*\xa5Gt]\xff{.\x97+\xa0r\t\xa0 \x13\xdbh3f̨\xe9t\xfae\x00\xdf0\f##\x84\xb8\x1c\xc0W\x10\\\x9c\xefk\x86a\\\x9b\xcdf\u007f\xdf:\r\xc7\x1f\xcc\xec\xeb\x86`\xe69\x00\xe64qj\xf2ݳt]\xbf\n\xc0y\xb5\xe8f\x18\xc6\xfb\x89hh4\xef,f\xfe\xb5\x94\xf2q\x00\x979\x8es\xb3\xef\x8bcooo?3\xcfe\xe6z\xc28\xf6\x05\xf0\x11\":\x15ţ\xa2\x17\x008\xa1\xf4\x02^\xeb>x+3w4\xda\xf3\x9c\xcdf73s\xb9\xd0\xe9\xd3t]\xffm*\x95\n\x95~\xbb\x1d)\xe5A\x00\xd6 \xf8\xdd\xe1\xbfl\xdb\xde\x1a\xd0\x17\xb4\xf7>$\x97\xcbU\x13\xcd@\xb9\\n)\x1aW\x05\xa4*\x94RA\xe9\x00\xf3\x13\x89D\xa8S\x92u]\xbf\x12\x01O\x11\x00_2M\xf3Ƕm\x87\xb1z\xee\xc04\xcdÅ\x10w\xc3?\x94\xfe0\x94\x8c5\x81\x96\x15\xd7u7)\xa5>\x85\x80\xfd\xf9(P\x00p\x96\xeb\xbaMq\f\x0e\f\f\xf4\x02(\xb7m;\xde\xf3\xbcǥ\x94\x86a\x18e\x17\xf8\xe2ŋ\xa7\x98\xa6y1\x8a\x85\xd8\x0e\b\x18\xd6_(\x14\xbe\x17$\x83\x88ʝax\xb1i\x9aWT\xda\xfa\x19\x86\xb1\x87\x94r9\x80\x86>q\xab\x81\x88\x82\f)횦\xad2\f\xe3\xc3C\x1b\r\xc3\xd8o{6\xdfvJ7\x91\xaf\"\xe0\x8c\x16\":\xaf\xbf\xbf\xff\x81R\xc1\x8c\xb2tvvF\xa5\x94q\"z\b\xc0;\x02\x86=\xa1\xebz7\x10\xc2\xfa\x94J\xa5\xf6-\x14\n\xb7\x865\xbd6\x89<\x803\x1cǹ\xb9\x99\x93$\x12\x89wj\x9a\xf6{T.\xd4\xd0\a\xe0\xb7\x00\xee#\xa2\x97<\xcf\xdb&\x84\u061d\x99\xdfEDG\x03\xf8\x04*\xf8q\x98\xf9\xdcR\x8cZ \xa6i\xdeOD\xe5^D_ \xa2\x1f\x03\xb8G\b\xf1\x8cR\xaa\x8f\x88tf>@)u\xaa\x10\xe2Ke\xce8\x1f\xce\xe7\xfc>\xdf\xd2S\xd0/\xeb\xee\x05\xc7q\xa6V\x12z\xd1E\x17\xbd#\x12\x89<\x8f\xe0hq\x05\xe0oD\xf4\x1c3O\x05p\b3\xcfw]w\xc4{\xb0\x94r\t\x80T\xb9\xf9\x98y-\x11ݢ\x94\xba7\x1a\x8d\xbe\xa8\x94z\xb3\xf4\x99\x1c\x04\xe0xf>\v\xe5\x8f\x15\xecc棷\xe7\x9aT\xb4\xcdwww\xbf\xb8u\xeb\xd69\xf0\xa9X\xd1\"61\xf3\x9cf/\x0e\xa0xVI\xe9\x10\xcfJY\x82\xbb\x038\x03\xc0\x95\xcc\xfc+!\xc4\x1d\x00\xae'\xa2o\xa3h\xa6.\xbb8\x88ȭ\xb48J㾁\xf25\xba\xf6c\xe6K\x99y\x8d\xe7y\x9b\x98y@)\xf5\x123?HD]>\x8b\xe3Y\x00ߪ4o#\xe9\xe9\xe9\xf9\a3_[f\x88\x00\xf0>f\xfe\x14\x8a\x95\xf4\x05\x00\xdf\xfc}]\xd7\x17Wx\xb2\xa2t\xdc[F\b\xf1\xa8\xe7y/\f\xf9L\xd60\xf3\xc5(\xbf8\xb6\x10\xd1\xe7\x87&b\x85r^-[\xb6l\xc0q\x9c\xf3P<б\x95'\x93\xde\x00\xe0\x88fm\xab\xfcp]\xf7\x8fB\x88\xd9\x00F\x98_\x1b\x013/\xc9d2V\x98\xb1\x8e\xe3\xdcW:-\xb7\x11\xf4\x11\xd1g\x112ź\x91h\x9av\t\xaa\xf8\xdd\x10ѼE\x8b\x16\x8d\x88[\xb3m[\xb5\xb5\xb5-@s\x8e\x82{\x9d\x99?\x91\xc9dV\x0fm\xac\xa6\x94\r\x1cǹY\xd7\xf5\x83\x98\xd9F\xf0y\x1a\x8d\xe01\"\x9a\xeb8\xce\xe9\x8e\xe3\xbc\xd6\xc4y|I\xa7\xd3\xcf*\xa5f\xa1h\xfe\xad\xfalB?\x98y\xa3R\xeaD\xd7u\x17U#\xb3\xbd\xbd\xfd;D\xe4g\xc1\xa9\x86\xf5\xcc|\\\xa3b˪%\x9dN\xbf\xac\x94:\t\xe1\xdfgw+\x14\n\x9f\xf7\xeb\xb0m\xbb\xe08\xce\xd9Dd\x00\b2pT\xcbjf\x9e\xe9w#\xaej\x81\x00\x80m\xdbo\xb9\xae{\x99\xa6i\xd3Q\xac\xf0\xf1t#4Dq+q73\u007f\xdaq\x9c\x99\xe5*n\xb7\x82l6\xbb\xd9q\x9cs\x99y.\x80z<\xf6\xaf3\xf3\xf7\x06\a\a?P:B\xba*l\xdbV\x99LF2\xf3\xb9(\x1e\\T\r\f\xe0Z\xa5ԑ\xae\xeb>V\xed܍$\x9b\xcd\xfe\x99\x88f\x02\xb8\x11\xe1n\x10e\xcb$e2\x99\xa5B\x88Ø\xf9\x96\x90\xf2\xfcx\x9a\x99\xcf\xd1u}n\xd0Q\v\r\t\xebL&\x93G(\xa5>\xc3\xccs\x88\xe8(\x84\v4\x04\x8a{\xfd\a\x88hM\xa1P\xb8i,\x1fRc\x18Ƈ\x85\x10_A\xd1\\:\xa3\xc2\xf0>\x00\x0f\x02\xf8\x95Rjy6\x9b\xf5\r\xb8\xab\x96\x85\v\x17\xb6M\x9a4\xe9\x02f>\x1d\xc0\xe1\b\xbe\xc1\xf5\x01\xb8\x89\x88z2\x99\xcc\x13C;L\xd3<\x9c\x88FD,\x10ѪL&\xf3\xdc\xf0\xf6D\"\xf1vM\xd3\xe6\xfḇ\xc5q\x9c\xe55\xfc\x190\f\xe3\xfd\x9a\xa6\x9d\x0e\xe0\x18f\x9e\x8eb\xfe\xfe\x9b\x00^e\xe6\x17\x01ܯi\xda\xeat:\xfd\x870\U000a4507\xa0X\xd5\xf2TT\xf0ݕ|r\xb73\xf3\r\x9b6mZY)ص\xe1q϶m\xc7\xfa\xfb\xfbg\x10сD4\x15E\x9f\xc7D\xa5\x94GD\xfdD4\x00\xe09\"z\xae\x15\xe1\xca\xcd\xc00\x8c\xfd\x88\xe8p\x00{\x96\x9c\x9fDD\xaf\x13\xd1f\x00ϵ\xb5\xb5\xad\xabƑW\v\x8b\x17/\x9e\x92\xcf\xe7?\x04`o\"\x9a\xa2\x94\x8a\x00x\x8d\x99\x9fزe\xcbc\xb585\xff?`Y\xd6ޞ\xe7\x1dLD\a\x94\xca\xc1j\x00\xde`\xe6\xd7\x01\xfc9̡}e<\x1e\x0f\xba\x835\x9cx<\xdeNDw\xa0\xb8H\x1bI\x84\x99{,\xcbJ6Xn3ٳB\x7fd\u0084\t\xbb\xb7D\x93Q\"Ri@2\x99\xdc'\x97\xcb\xfd\x06\xc0\x91-\xd0Ǐ\x8fG\xa3\xd1\xdf\x1b\x861/\x9b\xcd>\xd9\xec\xc9b\xb1\xd8rf\xfeP\x85a\xcf\x02\xb8\x1b\xc0\x13(\xbe;E\x85\x10{\x018\x8a\x99?\t\xe0mA\x172\xf3\x12\xd34\u05fb\xae\xbb\xa2qZ7\a\"z\x86\xb9\xec\xc3;700\xf0r\xb9\x01\xa6i\x9eBD\xfb\fog\xe6;\\\xd7\xddT\xaf\x8eͦ\xec\x021\f\xe3\xddJ\xa9U\x00f\xb4F\x1d\x7f\x88h:\x11ݓL&\xe7\xa6\xd3\xe9?5k\x1e˲>\xc3\xcc'\x97\x19\xb2N)%\xb3\xd9\xecJ\x04\x98r-˚\f\xe0\xcb\xcc|\x19\x80v\x9f!DD\xcb\xe2\xf1\xf8=\xbd\xbd\xbd\xaf6@\xed\xa61y\xf2\xe4\ar\xb9\xdc\xff\"\xf8\xe6x\xe5\x8f~\xf4\xa3\xc1\nb,\x00\x1f\xf3i?\t\xc0\x98_ \x81[\xac\xae\xae\xae\xe9B\x88\xbb0ʋc\b\xedJ\xa9w5Q>1s\xbaL\xff\xb5\xba\xae\x1f\x99\xcdf\x7f\x8b2~\x8eL&\xb3%\x93\xc9,UJ\xcd\x04\xf0\x97\x80a{F\xa3\xd1K\xeaQ\xb6\x15ض\xad\x00|\x0e>\x7f\a\x11ݤ\xeb\xfaŭת\xb5\xf8\xbe\x80\xa6R)\xdd\xf3\xbcG\x00\x1cT\x87\xec\xe7\x01lb\xe6W\x88\xe8U\x00\xbb1s;\x11\xcd\x00\xf0^\x00\x13\xab\x90\xb5\x95\x99;\\\xd7\xfdM\x1d\xfa\x94Ų\xacY\xcc\xfc\xb0_\x1f3_\xef\xba\ue668\xd2\x01\x98L&\xf7\xf1<\xefwD4ݧ;\x97\xcf\xe7\xa7\xf6\xf6\xf6\xf6עo+\x89\xc7\xe3\xbb\xc5b\xb1\xf9\x00\x8e,9|W\xb9\xae{w\x98kMӼ\x8f\x88F\x9f\x9f\xad\x94\xfa\x0f\xd7u\xff\xd8H\xd9!x#\xa0\xfdЖj\xb1\x8b1Ŏ-\x96R\xea\x02\x84\xb3,)\":#\x93ɬk\x86B%\xab\xcehXv\xfe\n\xe0?|\xdaON$\x12\xef,m\x05w1\x86I\xa5RS\x95R\x1fUJ\xbd\x87\x88\xf6ſ~\xdf[\x88h=\x80'\xdez\xeb\xadG\x96-[6\x10V&\x01\x80mۢ\xbf\xbf\xff\xb9\x00s\xe4pz\x1c\xc7IT\xad\xfd\x18Dz\xac\xf3\x98\xf9\xc7\x01ݷ\xe9\xba~Z\xab\xf2W,\xcb:\x80\x99\x17\rog\xe6\x17]\u05fd\xacN\xd9\t\xbfp}f\xbe\xca艹L&\xf7QJ\xf9\xcd\xf9\x86\xe38]\xdb\xffc\x18\xc6\x1c!\xc4\x02\x9fq\xa7\xe0_\xef\x95C\xb9\x03e\x1c\x85\xcc\xfc\xed0\x9e\xf6x<\xde\x1e\x8bž\f\xe0\x1c\x00\x1f\xa84\x1e\xc54\x8b\xbb\x98\xf9\xda\xf6\xf6\xf6\x9bJ\xbe\x9e@\"\x00000pl\xc8\xc5\xd1\x17\x89D.\r1n\xdc\xe1y\xde/\x85\x10?\x00\xb0\x9bO\xf7I\x03\x03\x03\xb7$\x12\x89\xf3[\xf1$QJ\xbd\x83\x88Flw\x89\xe8I\x00u-\x10f\x9e\a`\xae\x8f\xec\x95\x00F,\x10\xa5\xd4\xdb\xe1\xbf\xf5~\x01\xc0\x8e\x05BD\x87\x04\x8c\v\xe2\xc4r\x9d\x9a\xa6]\x892\vȶmQ\x8a*\xbf\f@5\xf1`Q\x00'\x12щ\xb9\\\xee/\x96e\xc53\x99\xcc]A\x83\x05\x00(\xa5>\x19R\xf8\x0f\x96,Y\xf2f\x15ʌ\x1b\xb2\xd9\xecf\"\xba.\xa8\x9f\x99\xe7i\x9a\xb6NJ\xf9\xcdT*լH\xe6]\x84@J\xb9g.\x97[\x05\xe0\xfb\xa8nq\f\xe7 f\xbeӲ\xactGG\x87od\xbb\x00\x00\":>\x840\xf6<\xef'u(3\x1e\xb8\x04\xc0\xebe\xfa\xdf\x0e\xe0r\xcf\xf36\x98\xa6\xd9cY\xd6a-\xd2k\x17%\xba\xba\xba\xa6\x03x\x18@\x98\xdfl\x18\x88\x99\xad\xe9ӧ_\xdf\xd9\xd9\x19\x1d\xde)J+'\xcc\x17\xfd\x87\xa5K\x97\xaeo\x90Rc\x92L&\xf3Ji\x1f\xedU\x18\xba;\x11}\x9d\x99\x1f\x93R>b\x9a\xe6W\xe2\xf1\xb8_`\xe2.\x1aH<\x1e߫P(\xac\x06p`\x85\xa1\x1e\x8a[\xc0\xc7Q\x8c\xbc\x0e\x93\xf6<_\xd7\xf5\xff\x1c\xde(f̘1\x03\xfe\xfb\xee\x9d`\xe6\xb5!&\x19\xf7\xa4\xd3\xe9;\x99\xf9\v(\xbe̅\xe1(\"\xba*\x1a\x8d\xbe$\xa5\xbcNJy\f\x1a\x94\xeb?\xce\xd8\x06\xa0\xcf\xe7_\xd0\xe78\x100\xbe\x0f@_\xa1P\xd8\xe9&\xd5\xd1ѡ\xc5b\xb1\x1bQ~q\xdc\xcf\xcc\xf3\xa3\xd1\xe8^\x8e\xe3Lu\x1c\xe7p\xc7q\xde\xed8N\xbb\xa6i\a\x11Q\x1cEke\x10\x9dRʳ\x866D\xc2F\xc8\n!j6\xebZ\x96u,3\a\x85r\xd4\xcb_\x1a\x1d\x8a\xe2\xba\xee/L\xd3|\x85\x88~\x8e`\x0f\xfbN\x10\xd1$\x14-)\xe7H)\x9f!\xa2k<\xcf\xfba6\x9b\xdd\xdcH\xdd\xc6*\xae\xeb^\x03\xe0\x9a\xe1\xed\xa6i\xae$\xa2\x11\xef\xb8\xcc|z5\xc1\x8a\xfb\xef\xbf\x7f\x8a\x99\x8f\t\xe8\xce1\xf3\x85\xae\xeb\xfe4\xe8\xfa\xee\xee\xee\xa7\x01\"\xfaY=9%\xba\xae\xf7\x10\xd1S>]S\xa2\xd1\xe8\xc9@q۰%\x8c0\xa5T\xa8'M\xab!\xa2I~\xe6\xb9fPz\xa28\x8e\xe3\x1c\xa6\x94:\x94\x99\x97\x00\xf8G\xd8\xeb\x89\xe83\x83\x83\x83\xab[Y\x84b\xbcS(\x14\xe6\xc1?_H)\xa5\xbeS\x8fl۶\v\xcc\xec\xeb\xba \xa2y@\xf1\t\x12\xaa\xf2\x9f\xa6i\xd3\xeaQ\xa6\x99\xf4\xf5\xf5\xd5\x1dq[-\xd9l\xf6I\xd7u\x17\xe5r\xb9iDt\n\x11݄\x10[0\":\"\x16\x8b\xad\xb6m;(zx\x17C \"_\x8f;3?T.)/,B\x88\xa0\x1c\xa6c\x00 \"\x84X\x1fFP\x85r\x9b\xa3I~Ŋ\x15\x95\xfc\x16M\xa3T\xb4\xe0V\x00\xb7\x96Rl\xbfND_Cѩ\x18ġ\xb9\\.\r\xe0\x82\x96(9\x8e!\xa2\x0f\xfbUV\x11B\x14,\xcb\xea\xf2\xb9\xa4*\x989(@\xf7\xc0T*\xa5Gt]\xff{.\x97+\xa0r\t\xa0 \x13\xdbh3f̨\xe9t\xfae\x00\xdf0\f##\x84\xb8\x1c\xc0W\x10\\\x9c\xefk\x86a\\\x9b\xcdf\x7f\xdf:\r\xc7\x1f\xcc\xec\xeb\x86`\xe69\x00\xe64qj\xf2ݳt]\xbf\n\xc0y\xb5\xe8f\x18\xc6\xfb\x89hh4\xef,f\xfe\xb5\x94\xf2q\x00\x979\x8es\xb3\xef\x8bcooo?3\xcfe\xe6z\xc28\xf6\x05\xf0\x11\":\x15ţ\xa2\x17\x008\xa1\xf4\x02^\xeb>x+3w4\xda\xf3\x9c\xcdf73s\xb9\xd0\xe9\xd3t]\xffm*\x95\n\x95~\xbb\x1d)\xe5A\x00\xd6 \xf8\xdd\xe1\xbfl\xdb\xde\x1a\xd0\x17\xb4\xf7>$\x97\xcbU\x13\xcd@\xb9\\n)\x1aW\x05\xa4*\x94RA\xe9\x00\xf3\x13\x89D\xa8S\x92u]\xbf\x12\x01O\x11\x00_2M\xf3Ƕm\x87\xb1z\xee\xc04\xcdÅ\x10w\xc3?\x94\xfe0\x94\x8c5\x81\x96\x15\xd7u7)\xa5>\x85\x80\xfd\xf9(P\x00p\x96\xeb\xbaMq\f\x0e\f\f\xf4\x02(\xb7m;\xde\xf3\xbcǥ\x94\x86a\x18e\x17\xf8\xe2ŋ\xa7\x98\xa6y1\x8a\x85\xd8\x0e\b\x18\xd6_(\x14\xbe\x17$\x83\x88ʝax\xb1i\x9aWT\xda\xfa\x19\x86\xb1\x87\x94r9\x80\x86>q\xab\x81\x88\x82\f)횦\xad2\f\xe3\xc3C\x1b\r\xc3\xd8o{6\xdfvJ7\x91\xaf\"\xe0\x8c\x16\":\xaf\xbf\xbf\xff\x81R\xc1\x8c\xb2tvvF\xa5\x94q\"z\b\xc0;\x02\x86=\xa1\xebz7\x10\xc2\xfa\x94J\xa5\xf6-\x14\n\xb7\x865\xbd6\x89<\x803\x1cǹ\xb9\x99\x93$\x12\x89wj\x9a\xf6{T.\xd4\xd0\a\xe0\xb7\x00\xee#\xa2\x97<\xcf\xdb&\x84\u061d\x99\xdfEDG\x03\xf8\x04*\xf8q\x98\xf9\xdcR\x8cZ \xa6i\xdeOD\xe5^D_ \xa2\x1f\x03\xb8G\b\xf1\x8cR\xaa\x8f\x88tf>@)u\xaa\x10\xe2Ke\xce8\x1f\xce\xe7\xfc>\xdf\xd2S\xd0/\xeb\xee\x05\xc7q\xa6V\x12z\xd1E\x17\xbd#\x12\x89<\x8f\xe0hq\x05\xe0oD\xf4\x1c3O\x05p\b3\xcfw]w\xc4{\xb0\x94r\t\x80T\xb9\xf9\x98y-\x11ݢ\x94\xba7\x1a\x8d\xbe\xa8\x94z\xb3\xf4\x99\x1c\x04\xe0xf>\v\xe5\x8f\x15\xecc棷\xe7\x9aT\xb4\xcdwww\xbf\xb8u\xeb\xd69\xf0\xa9X\xd1\"61\xf3\x9cf/\x0e\xa0xVI\xe9\x10\xcfJY\x82\xbb\x038\x03\xc0\x95\xcc\xfc+!\xc4\x1d\x00\xae'\xa2o\xa3h\xa6.\xbb8\x88ȭ\xb48J㾁\xf25\xba\xf6c\xe6K\x99y\x8d\xe7y\x9b\x98y@)\xf5\x123?HD]>\x8b\xe3Y\x00ߪ4o#\xe9\xe9\xe9\xf9\a3_[f\x88\x00\xf0>f\xfe\x14\x8a\x95\xf4\x05\x00\xdf\xfc}]\xd7\x17Wx\xb2\xa2t\xdc[F\b\xf1\xa8\xe7y/\f\xf9L\xd60\xf3\xc5(\xbf8\xb6\x10\xd1\xe7\x87&b\x85r^-[\xb6l\xc0q\x9c\xf3P<б\x95'\x93\xde\x00\xe0\x88fm\xab\xfcp]\xf7\x8fB\x88\xd9\x00F\x98_\x1b\x013/\xc9d2V\x98\xb1\x8e\xe3\xdcW:-\xb7\x11\xf4\x11\xd1g\x112ź\x91h\x9av\t\xaa\xf8\xdd\x10ѼE\x8b\x16\x8d\x88[\xb3m[\xb5\xb5\xb5-@s\x8e\x82{\x9d\x99?\x91\xc9dV\x0fm\xac\xa6\x94\r\x1cǹY\xd7\xf5\x83\x98\xd9F\xf0y\x1a\x8d\xe01\"\x9a\xeb8\xce\xe9\x8e\xe3\xbc\xd6\xc4y|I\xa7\xd3\xcf*\xa5f\xa1h\xfe\xad\xfalB?\x98y\xa3R\xeaD\xd7u\x17U#\xb3\xbd\xbd\xfd;D\xe4g\xc1\xa9\x86\xf5\xcc|\\\xa3b˪%\x9dN\xbf\xac\x94:\t\xe1\xdfgw+\x14\n\x9f\xf7\xeb\xb0m\xbb\xe08\xce\xd9Dd\x00\b2pT\xcbjf\x9e\xe9w#\xaej\x81\x00\x80m\xdbo\xb9\xae{\x99\xa6i\xd3Q\xac\xf0\xf1t#4Dq+q73\x7f\xdaq\x9c\x99\xe5*n\xb7\x82l6\xbb\xd9q\x9cs\x99y.\x80z<\xf6\xaf3\xf3\xf7\x06\a\a?P:B\xba*l\xdbV\x99LF2\xf3\xb9(\x1e\\T\r\f\xe0Z\xa5ԑ\xae\xeb>V\xed܍$\x9b\xcd\xfe\x99\x88f\x02\xb8\x11\xe1n\x10e\xcb$e2\x99\xa5B\x88Ø\xf9\x96\x90\xf2\xfcx\x9a\x99\xcf\xd1u}n\xd0Q\v\r\t\xebL&\x93G(\xa5>\xc3\xccs\x88\xe8(\x84\v4\x04\x8a{\xfd\a\x88hM\xa1P\xb8i,\x1fRc\x18Ƈ\x85\x10_A\xd1\\:\xa3\xc2\xf0>\x00\x0f\x02\xf8\x95Rjy6\x9b\xf5\r\xb8\xab\x96\x85\v\x17\xb6M\x9a4\xe9\x02f>\x1d\xc0\xe1\b\xbe\xc1\xf5\x01\xb8\x89\x88z2\x99\xcc\x13C;L\xd3<\x9c\x88FD,\x10ѪL&\xf3\xdc\xf0\xf6D\"\xf1vM\xd3\xe6\xfḇ\xc5q\x9c\xe55\xfc\x190\f\xe3\xfd\x9a\xa6\x9d\x0e\xe0\x18f\x9e\x8eb\xfe\xfe\x9b\x00^e\xe6\x17\x01ܯi\xda\xeat:\xfd\x870\U000a4507\xa0X\xd5\xf2TT\xf0ݕ|r\xb73\xf3\r\x9b6mZY)ص\xe1q϶m\xc7\xfa\xfb\xfbg\x10сD4\x15E\x9f\xc7D\xa5\x94GD\xfdD4\x00\xe09\"z\xae\x15\xe1\xca\xcd\xc00\x8c\xfd\x88\xe8p\x00{\x96\x9c\x9fDD\xaf\x13\xd1f\x00ϵ\xb5\xb5\xad\xabƑW\v\x8b\x17/\x9e\x92\xcf\xe7?\x04`o\"\x9a\xa2\x94\x8a\x00x\x8d\x99\x9fزe\xcbc\xb585\xff?`Y\xd6ޞ\xe7\x1dLD\a\x94\xca\xc1j\x00\xde`\xe6\xd7\x01\xfc9̡