From 698b9e2acc4daafe7d2b314e2d8c96545dde9c40 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Thu, 26 Mar 2015 17:11:47 -0400 Subject: #1070 Clearer error message for illegal characters --- models/user.go | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'models/user.go') diff --git a/models/user.go b/models/user.go index dcfd0dc5..bf69f97a 100644 --- a/models/user.go +++ b/models/user.go @@ -36,10 +36,8 @@ const ( ) var ( - ErrUserAlreadyExist = errors.New("User already exist") ErrUserNotExist = errors.New("User does not exist") ErrUserNotKeyOwner = errors.New("User does not the owner of public key") - ErrEmailAlreadyUsed = errors.New("E-mail already used") ErrEmailNotExist = errors.New("E-mail does not exist") ErrEmailNotActivated = errors.New("E-mail address has not been activated") ErrUserNameIllegal = errors.New("User name contains illegal characters") @@ -273,23 +271,23 @@ func GetUserSalt() string { } // CreateUser creates record of a new user. -func CreateUser(u *User) error { - if !IsLegalName(u.Name) { - return ErrUserNameIllegal +func CreateUser(u *User) (err error) { + if err = IsUsableName(u.Name); err != nil { + return err } isExist, err := IsUserExist(0, u.Name) if err != nil { return err } else if isExist { - return ErrUserAlreadyExist + return ErrUserAlreadyExist{u.Name} } isExist, err = IsEmailUsed(u.Email) if err != nil { return err } else if isExist { - return ErrEmailAlreadyUsed + return ErrEmailAlreadyUsed{u.Email} } u.LowerName = strings.ToLower(u.Name) @@ -392,8 +390,15 @@ func VerifyActiveEmailCode(code, email string) *EmailAddress { // ChangeUserName changes all corresponding setting from old user name to new one. func ChangeUserName(u *User, newUserName string) (err error) { - if !IsLegalName(newUserName) { - return ErrUserNameIllegal + if err = IsUsableName(newUserName); err != nil { + return err + } + + isExist, err := IsUserExist(0, newUserName) + if err != nil { + return err + } else if isExist { + return ErrUserAlreadyExist{newUserName} } return os.Rename(UserPath(u.LowerName), UserPath(newUserName)) @@ -405,7 +410,7 @@ func UpdateUser(u *User) error { if err != nil { return err } else if has { - return ErrEmailAlreadyUsed + return ErrEmailAlreadyUsed{u.Email} } u.LowerName = strings.ToLower(u.Name) @@ -641,7 +646,7 @@ func AddEmailAddress(email *EmailAddress) error { if err != nil { return err } else if used { - return ErrEmailAlreadyUsed + return ErrEmailAlreadyUsed{email.Email} } _, err = x.Insert(email) -- cgit v1.2.3 From f78046fc3be8db80f8ac44512237c92825540e5d Mon Sep 17 00:00:00 2001 From: Dustin Willis Webber Date: Thu, 16 Apr 2015 14:36:32 -0400 Subject: typo fix --- models/login.go | 2 +- models/user.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'models/user.go') diff --git a/models/login.go b/models/login.go index 916e2731..73d11256 100644 --- a/models/login.go +++ b/models/login.go @@ -169,7 +169,7 @@ func UserSignIn(uname, passwd string) (*User, error) { // For plain login, user must exist to reach this line. // Now verify password. if u.LoginType == PLAIN { - if !u.ValidtePassword(passwd) { + if !u.ValidatePassword(passwd) { return nil, ErrUserNotExist } return u, nil diff --git a/models/user.go b/models/user.go index dcfd0dc5..8651464e 100644 --- a/models/user.go +++ b/models/user.go @@ -146,7 +146,7 @@ func (u *User) EncodePasswd() { } // ValidtePassword checks if given password matches the one belongs to the user. -func (u *User) ValidtePassword(passwd string) bool { +func (u *User) ValidatePassword(passwd string) bool { newUser := &User{Passwd: passwd, Salt: u.Salt} newUser.EncodePasswd() return u.Passwd == newUser.Passwd -- cgit v1.2.3 From e57594dc31fc42c1bb7ba0df77d1d4f249f8f079 Mon Sep 17 00:00:00 2001 From: Dustin Willis Webber Date: Thu, 16 Apr 2015 14:40:39 -0400 Subject: typo fix for comment --- models/user.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'models/user.go') diff --git a/models/user.go b/models/user.go index 8651464e..e0ba4be3 100644 --- a/models/user.go +++ b/models/user.go @@ -145,7 +145,7 @@ func (u *User) EncodePasswd() { u.Passwd = fmt.Sprintf("%x", newPasswd) } -// ValidtePassword checks if given password matches the one belongs to the user. +// ValidatePassword checks if given password matches the one belongs to the user. func (u *User) ValidatePassword(passwd string) bool { newUser := &User{Passwd: passwd, Salt: u.Salt} newUser.EncodePasswd() -- cgit v1.2.3 From e50982f5ec78c3cfa4a1cf322f7fa1a4dea44b84 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Wed, 5 Aug 2015 11:14:17 +0800 Subject: allow anonymous SSH clone --- cmd/serve.go | 94 ++++++++++++++++++++++++---------------------- gogs.go | 2 +- models/error.go | 14 +++++++ models/issue.go | 4 +- models/login.go | 12 +++--- models/repo.go | 2 +- models/user.go | 13 +++---- modules/auth/auth.go | 6 +-- modules/middleware/org.go | 2 +- modules/middleware/repo.go | 4 +- routers/api/v1/repo.go | 6 +-- routers/api/v1/user.go | 2 +- routers/org/members.go | 2 +- routers/org/teams.go | 2 +- routers/repo/http.go | 4 +- routers/repo/repo.go | 2 +- routers/repo/setting.go | 6 +-- routers/user/auth.go | 8 ++-- routers/user/home.go | 14 +++---- templates/.VERSION | 2 +- 20 files changed, 109 insertions(+), 92 deletions(-) (limited to 'models/user.go') diff --git a/cmd/serve.go b/cmd/serve.go index fed65bba..ecf07114 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -78,35 +78,18 @@ func runServ(c *cli.Context) { setup("serv.log") fail := func(userMessage, logMessage string, args ...interface{}) { - fmt.Fprintln(os.Stderr, "Gogs: ", userMessage) - log.GitLogger.Fatal(2, logMessage, args...) + fmt.Fprintln(os.Stderr, "Gogs:", userMessage) + log.GitLogger.Fatal(3, logMessage, args...) } if len(c.Args()) < 1 { fail("Not enough arguments", "Not enough arguments") } - keys := strings.Split(c.Args()[0], "-") - if len(keys) != 2 { - fail("key-id format error", "Invalid key id: %s", c.Args()[0]) - } - - keyId, err := com.StrTo(keys[1]).Int64() - if err != nil { - fail("key-id format error", "Invalid key id: %s", err) - } - - user, err := models.GetUserByKeyId(keyId) - if err != nil { - fail("internal error", "Failed to get user by key ID(%d): %v", keyId, err) - } - cmd := os.Getenv("SSH_ORIGINAL_COMMAND") - if cmd == "" { - fmt.Printf("Hi, %s! You've successfully authenticated, but Gogs does not provide shell access.\n", user.Name) - if user.IsAdmin { - println("If this is unexpected, please log in with password and setup Gogs under another user.") - } + if len(cmd) == 0 { + println("Hi there, You've successfully authenticated, but Gogs does not provide shell access.") + println("If this is unexpected, please log in with password and setup Gogs under another user.") return } @@ -121,7 +104,7 @@ func runServ(c *cli.Context) { repoUser, err := models.GetUserByName(repoUserName) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { fail("Repository owner does not exist", "Unregistered owner: %s", repoUserName) } fail("Internal error", "Failed to get repository owner(%s): %v", repoUserName, err) @@ -130,11 +113,7 @@ func runServ(c *cli.Context) { repo, err := models.GetRepositoryByName(repoUser.Id, repoName) if err != nil { if models.IsErrRepoNotExist(err) { - if user.Id == repoUser.Id || repoUser.IsOwnedBy(user.Id) { - fail("Repository does not exist", "Repository does not exist: %s/%s", repoUser.Name, repoName) - } else { - fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", repoUser.Name, repoName) - } + fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", repoUser.Name, repoName) } fail("Internal error", "Failed to get repository: %v", err) } @@ -144,17 +123,39 @@ func runServ(c *cli.Context) { fail("Unknown git command", "Unknown git command %s", verb) } - mode, err := models.AccessLevel(user, repo) - if err != nil { - fail("Internal error", "Fail to check access: %v", err) - } else if mode < requestedMode { - clientMessage := _ACCESS_DENIED_MESSAGE - if mode >= models.ACCESS_MODE_READ { - clientMessage = "You do not have sufficient authorization for this action" + // Allow anonymous clone for public repositories. + var ( + keyID int64 + user *models.User + ) + if requestedMode == models.ACCESS_MODE_WRITE || repo.IsPrivate { + keys := strings.Split(c.Args()[0], "-") + if len(keys) != 2 { + fail("key-id format error", "Invalid key id: %s", c.Args()[0]) + } + + keyID, err = com.StrTo(keys[1]).Int64() + if err != nil { + fail("key-id format error", "Invalid key id: %s", err) + } + + user, err = models.GetUserByKeyId(keyID) + if err != nil { + fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err) + } + + mode, err := models.AccessLevel(user, repo) + if err != nil { + fail("Internal error", "Fail to check access: %v", err) + } else if mode < requestedMode { + clientMessage := _ACCESS_DENIED_MESSAGE + if mode >= models.ACCESS_MODE_READ { + clientMessage = "You do not have sufficient authorization for this action" + } + fail(clientMessage, + "User %s does not have level %v access to repository %s", + user.Name, requestedMode, repoPath) } - fail(clientMessage, - "User %s does not have level %v access to repository %s", - user.Name, requestedMode, repoPath) } uuid := uuid.NewV4().String() @@ -201,12 +202,15 @@ func runServ(c *cli.Context) { } // Update key activity. - key, err := models.GetPublicKeyById(keyId) - if err != nil { - fail("Internal error", "GetPublicKeyById: %v", err) - } - key.Updated = time.Now() - if err = models.UpdatePublicKey(key); err != nil { - fail("Internal error", "UpdatePublicKey: %v", err) + if keyID > 0 { + key, err := models.GetPublicKeyById(keyID) + if err != nil { + fail("Internal error", "GetPublicKeyById: %v", err) + } + + key.Updated = time.Now() + if err = models.UpdatePublicKey(key); err != nil { + fail("Internal error", "UpdatePublicKey: %v", err) + } } } diff --git a/gogs.go b/gogs.go index 712f8606..1513bbfa 100644 --- a/gogs.go +++ b/gogs.go @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.6.3.0802 Beta" +const APP_VER = "0.6.3.0805 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/error.go b/models/error.go index 04f850de..067eace2 100644 --- a/models/error.go +++ b/models/error.go @@ -54,6 +54,20 @@ func (err ErrUserAlreadyExist) Error() string { return fmt.Sprintf("user already exists: [name: %s]", err.Name) } +type ErrUserNotExist struct { + UID int64 + Name string +} + +func IsErrUserNotExist(err error) bool { + _, ok := err.(ErrUserNotExist) + return ok +} + +func (err ErrUserNotExist) Error() string { + return fmt.Sprintf("user does not exist: [uid: %d, name: %s]", err.UID, err.Name) +} + type ErrEmailAlreadyUsed struct { Email string } diff --git a/models/issue.go b/models/issue.go index f9930aa6..77b38cbc 100644 --- a/models/issue.go +++ b/models/issue.go @@ -57,7 +57,7 @@ type Issue struct { func (i *Issue) GetPoster() (err error) { i.Poster, err = GetUserById(i.PosterId) - if err == ErrUserNotExist { + if IsErrUserNotExist(err) { i.Poster = &User{Name: "FakeUser"} return nil } @@ -92,7 +92,7 @@ func (i *Issue) GetAssignee() (err error) { return nil } i.Assignee, err = GetUserById(i.AssigneeId) - if err == ErrUserNotExist { + if IsErrUserNotExist(err) { return nil } return err diff --git a/models/login.go b/models/login.go index 10f782be..82cea35f 100644 --- a/models/login.go +++ b/models/login.go @@ -41,7 +41,7 @@ var ( var LoginTypes = map[LoginType]string{ LDAP: "LDAP", SMTP: "SMTP", - PAM: "PAM", + PAM: "PAM", } // Ensure structs implemented interface. @@ -192,7 +192,7 @@ func UserSignIn(uname, passwd string) (*User, error) { // Now verify password. if u.LoginType == PLAIN { if !u.ValidatePassword(passwd) { - return nil, ErrUserNotExist + return nil, ErrUserNotExist{u.Id, u.Name} } return u, nil } @@ -229,7 +229,7 @@ func UserSignIn(uname, passwd string) (*User, error) { } } - return nil, ErrUserNotExist + return nil, ErrUserNotExist{u.Id, u.Name} } var source LoginSource @@ -261,7 +261,7 @@ func LoginUserLdapSource(u *User, name, passwd string, sourceId int64, cfg *LDAP name, fn, sn, mail, logged := cfg.Ldapsource.SearchEntry(name, passwd) if !logged { // User not in LDAP, do nothing - return nil, ErrUserNotExist + return nil, ErrUserNotExist{u.Id, u.Name} } if !autoRegister { return u, nil @@ -362,7 +362,7 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP if err := SmtpAuth(cfg.Host, cfg.Port, auth, cfg.TLS); err != nil { if strings.Contains(err.Error(), "Username and Password not accepted") { - return nil, ErrUserNotExist + return nil, ErrUserNotExist{u.Id, u.Name} } return nil, err } @@ -397,7 +397,7 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP func LoginUserPAMSource(u *User, name, passwd string, sourceId int64, cfg *PAMConfig, autoRegister bool) (*User, error) { if err := pam.PAMAuth(cfg.ServiceName, name, passwd); err != nil { if strings.Contains(err.Error(), "Authentication failure") { - return nil, ErrUserNotExist + return nil, ErrUserNotExist{u.Id, u.Name} } return nil, err } diff --git a/models/repo.go b/models/repo.go index a2b29ff3..117837fc 100644 --- a/models/repo.go +++ b/models/repo.go @@ -624,7 +624,7 @@ func GetRepositoriesWithUsers(num, offset int) ([]*Repository, error) { if err != nil { return nil, err } else if !has { - return nil, ErrUserNotExist + return nil, ErrUserNotExist{repo.OwnerId, ""} } } diff --git a/models/user.go b/models/user.go index e239ea17..c5d4b9d9 100644 --- a/models/user.go +++ b/models/user.go @@ -36,7 +36,6 @@ const ( ) var ( - ErrUserNotExist = errors.New("User does not exist") ErrUserNotKeyOwner = errors.New("User does not the owner of public key") ErrEmailNotExist = errors.New("E-mail does not exist") ErrEmailNotActivated = errors.New("E-mail address has not been activated") @@ -555,7 +554,7 @@ func getUserById(e Engine, id int64) (*User, error) { if err != nil { return nil, err } else if !has { - return nil, ErrUserNotExist + return nil, ErrUserNotExist{id, ""} } return u, nil } @@ -568,14 +567,14 @@ func GetUserById(id int64) (*User, error) { // GetUserByName returns user by given name. func GetUserByName(name string) (*User, error) { if len(name) == 0 { - return nil, ErrUserNotExist + return nil, ErrUserNotExist{0, name} } u := &User{LowerName: strings.ToLower(name)} has, err := x.Get(u) if err != nil { return nil, err } else if !has { - return nil, ErrUserNotExist + return nil, ErrUserNotExist{0, name} } return u, nil } @@ -700,7 +699,7 @@ func MakeEmailPrimary(email *EmailAddress) error { if err != nil { return err } else if !has { - return ErrUserNotExist + return ErrUserNotExist{email.Uid, ""} } // Make sure the former primary email doesn't disappear @@ -763,7 +762,7 @@ func ValidateCommitsWithEmails(oldCommits *list.List) *list.List { // GetUserByEmail returns the user object by given e-mail if exists. func GetUserByEmail(email string) (*User, error) { if len(email) == 0 { - return nil, ErrUserNotExist + return nil, ErrUserNotExist{0, "email"} } // First try to find the user by primary email user := &User{Email: strings.ToLower(email)} @@ -785,7 +784,7 @@ func GetUserByEmail(email string) (*User, error) { return GetUserById(emailAddress.Uid) } - return nil, ErrUserNotExist + return nil, ErrUserNotExist{0, "email"} } // SearchUserByName returns given number of users whose name contains keyword. diff --git a/modules/auth/auth.go b/modules/auth/auth.go index 155a8272..7e01abc3 100644 --- a/modules/auth/auth.go +++ b/modules/auth/auth.go @@ -55,7 +55,7 @@ func SignedInId(req *http.Request, sess session.Store) int64 { } if id, ok := uid.(int64); ok { if _, err := models.GetUserById(id); err != nil { - if err != models.ErrUserNotExist { + if !models.IsErrUserNotExist(err) { log.Error(4, "GetUserById: %v", err) } return 0 @@ -80,7 +80,7 @@ func SignedInUser(req *http.Request, sess session.Store) (*models.User, bool) { if len(webAuthUser) > 0 { u, err := models.GetUserByName(webAuthUser) if err != nil { - if err != models.ErrUserNotExist { + if !models.IsErrUserNotExist(err) { log.Error(4, "GetUserByName: %v", err) return nil, false } @@ -115,7 +115,7 @@ func SignedInUser(req *http.Request, sess session.Store) (*models.User, bool) { u, err := models.UserSignIn(uname, passwd) if err != nil { - if err != models.ErrUserNotExist { + if !models.IsErrUserNotExist(err) { log.Error(4, "UserSignIn: %v", err) } return nil, false diff --git a/modules/middleware/org.go b/modules/middleware/org.go index 1ac4bcf1..065e1b1e 100644 --- a/modules/middleware/org.go +++ b/modules/middleware/org.go @@ -34,7 +34,7 @@ func OrgAssignment(redirect bool, args ...bool) macaron.Handler { var err error ctx.Org.Organization, err = models.GetUserByName(orgName) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Handle(404, "GetUserByName", err) } else if redirect { log.Error(4, "GetUserByName", err) diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go index 0aaecec8..c14df275 100644 --- a/modules/middleware/repo.go +++ b/modules/middleware/repo.go @@ -41,7 +41,7 @@ func ApiRepoAssignment() macaron.Handler { } else { u, err = models.GetUserByName(userName) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Error(404) } else { ctx.JSON(500, &base.ApiJsonErr{"GetUserByName: " + err.Error(), base.DOC_URL}) @@ -217,7 +217,7 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler { } else { u, err = models.GetUserByName(userName) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Handle(404, "GetUserByName", err) } else { ctx.Handle(500, "GetUserByName", err) diff --git a/routers/api/v1/repo.go b/routers/api/v1/repo.go index 7da5f817..d683eac3 100644 --- a/routers/api/v1/repo.go +++ b/routers/api/v1/repo.go @@ -139,7 +139,7 @@ func CreateRepo(ctx *middleware.Context, opt api.CreateRepoOption) { func CreateOrgRepo(ctx *middleware.Context, opt api.CreateRepoOption) { org, err := models.GetOrgByName(ctx.Params(":org")) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Error(404) } else { ctx.Error(500) @@ -157,7 +157,7 @@ func CreateOrgRepo(ctx *middleware.Context, opt api.CreateRepoOption) { func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) { u, err := models.GetUserByName(ctx.Query("username")) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.HandleAPI(422, err) } else { ctx.HandleAPI(500, err) @@ -174,7 +174,7 @@ func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) { if form.Uid != u.Id { org, err := models.GetUserById(form.Uid) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.HandleAPI(422, err) } else { ctx.HandleAPI(500, err) diff --git a/routers/api/v1/user.go b/routers/api/v1/user.go index a4648297..feecda48 100644 --- a/routers/api/v1/user.go +++ b/routers/api/v1/user.go @@ -61,7 +61,7 @@ func SearchUsers(ctx *middleware.Context) { func GetUserInfo(ctx *middleware.Context) { u, err := models.GetUserByName(ctx.Params(":username")) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Error(404) } else { ctx.JSON(500, &base.ApiJsonErr{"GetUserByName: " + err.Error(), base.DOC_URL}) diff --git a/routers/org/members.go b/routers/org/members.go index c8c90cfe..dd742bb7 100644 --- a/routers/org/members.go +++ b/routers/org/members.go @@ -100,7 +100,7 @@ func Invitation(ctx *middleware.Context) { uname := ctx.Query("uname") u, err := models.GetUserByName(uname) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Flash.Error(ctx.Tr("form.user_not_exist")) ctx.Redirect(ctx.Org.OrgLink + "/invitations/new") } else { diff --git a/routers/org/teams.go b/routers/org/teams.go index 7436e30e..6968512f 100644 --- a/routers/org/teams.go +++ b/routers/org/teams.go @@ -77,7 +77,7 @@ func TeamsAction(ctx *middleware.Context) { var u *models.User u, err = models.GetUserByName(uname) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Flash.Error(ctx.Tr("form.user_not_exist")) ctx.Redirect(ctx.Org.OrgLink + "/teams/" + ctx.Org.Team.LowerName) } else { diff --git a/routers/repo/http.go b/routers/repo/http.go index 4e5aba04..45b0ec59 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -55,7 +55,7 @@ func Http(ctx *middleware.Context) { repoUser, err := models.GetUserByName(username) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Handle(404, "GetUserByName", nil) } else { ctx.Handle(500, "GetUserByName", err) @@ -107,7 +107,7 @@ func Http(ctx *middleware.Context) { authUser, err = models.UserSignIn(authUsername, authPasswd) if err != nil { - if err != models.ErrUserNotExist { + if !models.IsErrUserNotExist(err) { ctx.Handle(500, "UserSignIn error: %v", err) return } diff --git a/routers/repo/repo.go b/routers/repo/repo.go index 605071d1..f8df726c 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -35,7 +35,7 @@ func checkContextUser(ctx *middleware.Context, uid int64) *models.User { } org, err := models.GetUserById(uid) - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { return ctx.User } diff --git a/routers/repo/setting.go b/routers/repo/setting.go index c3714808..12fc428c 100644 --- a/routers/repo/setting.go +++ b/routers/repo/setting.go @@ -118,7 +118,7 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) { } if _, err = models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), SETTINGS_OPTIONS, nil) } else { ctx.Handle(500, "UserSignIn", err) @@ -151,7 +151,7 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) { } if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), SETTINGS_OPTIONS, nil) } else { ctx.Handle(500, "UserSignIn", err) @@ -185,7 +185,7 @@ func SettingsCollaboration(ctx *middleware.Context) { u, err := models.GetUserByName(name) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Flash.Error(ctx.Tr("form.user_not_exist")) ctx.Redirect(setting.AppSubUrl + ctx.Req.URL.Path) } else { diff --git a/routers/user/auth.go b/routers/user/auth.go index 52675a77..4b29a29e 100644 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -60,7 +60,7 @@ func SignIn(ctx *middleware.Context) { u, err := models.GetUserByName(uname) if err != nil { - if err != models.ErrUserNotExist { + if !models.IsErrUserNotExist(err) { ctx.Handle(500, "GetUserByName", err) } else { ctx.HTML(200, SIGNIN) @@ -105,7 +105,7 @@ func SignInPost(ctx *middleware.Context, form auth.SignInForm) { u, err := models.UserSignIn(form.UserName, form.Password) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), SIGNIN, &form) } else { ctx.Handle(500, "UserSignIn", err) @@ -328,7 +328,7 @@ func Activate(ctx *middleware.Context) { user.IsActive = true user.Rands = models.GetUserSalt() if err := models.UpdateUser(user); err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Error(404) } else { ctx.Handle(500, "UpdateUser", err) @@ -391,7 +391,7 @@ func ForgotPasswdPost(ctx *middleware.Context) { email := ctx.Query("email") u, err := models.GetUserByEmail(email) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Data["Err_Email"] = true ctx.RenderWithErr(ctx.Tr("auth.email_not_associate"), FORGOT_PASSWORD, nil) } else { diff --git a/routers/user/home.go b/routers/user/home.go index 503f9e36..5e77b837 100644 --- a/routers/user/home.go +++ b/routers/user/home.go @@ -38,7 +38,7 @@ func Dashboard(ctx *middleware.Context) { // Organization. org, err := models.GetUserByName(orgName) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Handle(404, "GetUserByName", err) } else { ctx.Handle(500, "GetUserByName", err) @@ -115,7 +115,7 @@ func Dashboard(ctx *middleware.Context) { // FIXME: cache results? u, err := models.GetUserByName(act.ActUserName) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { continue } ctx.Handle(500, "GetUserByName", err) @@ -176,7 +176,7 @@ func Profile(ctx *middleware.Context) { u, err := models.GetUserByName(uname) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { ctx.Handle(404, "GetUserByName", err) } else { ctx.Handle(500, "GetUserByName", err) @@ -223,7 +223,7 @@ func Profile(ctx *middleware.Context) { // FIXME: cache results? u, err := models.GetUserByName(act.ActUserName) if err != nil { - if err == models.ErrUserNotExist { + if models.IsErrUserNotExist(err) { continue } ctx.Handle(500, "GetUserByName", err) @@ -247,10 +247,10 @@ func Profile(ctx *middleware.Context) { func Email2User(ctx *middleware.Context) { u, err := models.GetUserByEmail(ctx.Query("email")) if err != nil { - if err == models.ErrUserNotExist { - ctx.Handle(404, "user.Email2User(GetUserByEmail)", err) + if models.IsErrUserNotExist(err) { + ctx.Handle(404, "GetUserByEmail", err) } else { - ctx.Handle(500, "user.Email2User(GetUserByEmail)", err) + ctx.Handle(500, "GetUserByEmail", err) } return } diff --git a/templates/.VERSION b/templates/.VERSION index 8c77c216..2d7fe898 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.6.3.0802 Beta \ No newline at end of file +0.6.3.0805 Beta \ No newline at end of file -- cgit v1.2.3 From b9527cd1bfabcce3be62b43f0c199b1418519549 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Wed, 5 Aug 2015 17:36:22 +0800 Subject: #1299 force downcase e-mail --- models/user.go | 22 +++++++++++++++------- public/js/app.js | 2 +- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'models/user.go') diff --git a/models/user.go b/models/user.go index c5d4b9d9..4b6517d7 100644 --- a/models/user.go +++ b/models/user.go @@ -258,6 +258,8 @@ func IsEmailUsed(email string) (bool, error) { if len(email) == 0 { return false, nil } + + email = strings.ToLower(email) if has, err := x.Get(&EmailAddress{Email: email}); has || err != nil { return has, err } @@ -405,6 +407,7 @@ func ChangeUserName(u *User, newUserName string) (err error) { // UpdateUser updates user's information. func UpdateUser(u *User) error { + u.Email = strings.ToLower(u.Email) has, err := x.Where("id!=?", u.Id).And("type=?", u.Type).And("email=?", u.Email).Get(new(User)) if err != nil { return err @@ -641,6 +644,7 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) { } func AddEmailAddress(email *EmailAddress) error { + email.Email = strings.ToLower(email.Email) used, err := IsEmailUsed(email.Email) if err != nil { return err @@ -674,7 +678,7 @@ func DeleteEmailAddress(email *EmailAddress) error { return ErrEmailNotExist } - if _, err = x.Delete(email); err != nil { + if _, err = x.Id(email.Id).Delete(email); err != nil { return err } @@ -736,13 +740,15 @@ func ValidateCommitWithEmail(c *git.Commit) *User { // ValidateCommitsWithEmails checks if authors' e-mails of commits are corresponding to users. func ValidateCommitsWithEmails(oldCommits *list.List) *list.List { - emails := map[string]*User{} - newCommits := list.New() - e := oldCommits.Front() + var ( + u *User + emails = map[string]*User{} + newCommits = list.New() + e = oldCommits.Front() + ) for e != nil { c := e.Value.(*git.Commit) - var u *User if v, ok := emails[c.Author.Email]; !ok { u, _ = GetUserByEmail(c.Author.Email) emails[c.Author.Email] = u @@ -764,8 +770,10 @@ func GetUserByEmail(email string) (*User, error) { if len(email) == 0 { return nil, ErrUserNotExist{0, "email"} } + + email = strings.ToLower(email) // First try to find the user by primary email - user := &User{Email: strings.ToLower(email)} + user := &User{Email: email} has, err := x.Get(user) if err != nil { return nil, err @@ -775,7 +783,7 @@ func GetUserByEmail(email string) (*User, error) { } // Otherwise, check in alternative list for activated email addresses - emailAddress := &EmailAddress{Email: strings.ToLower(email), IsActivated: true} + emailAddress := &EmailAddress{Email: email, IsActivated: true} has, err = x.Get(emailAddress) if err != nil { return nil, err diff --git a/public/js/app.js b/public/js/app.js index 3dbf29c1..8eb19a0a 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -297,7 +297,7 @@ var Gogits = {}; } else { $(selector).zclip({ - path: Gogs.AppSubUrl + "/js/ZeroClipboard.swf", + path: Gogits.AppSubUrl + "/js/ZeroClipboard.swf", copy: function () { var t = $(this).data("copy-val"); var to = $($(this).data("copy-from")); -- cgit v1.2.3 From 39a3b768bc8b0288cb4aa91d27485f46cfbfeb29 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Thu, 6 Aug 2015 22:48:11 +0800 Subject: #334: Add Deployment Key Support --- .gopmfile | 4 +- cmd/serve.go | 71 ++++--- cmd/web.go | 7 + conf/locale/locale_en-US.ini | 22 +- gogs.go | 2 +- models/error.go | 76 +++++++ models/issue.go | 18 +- models/migrations/migrations.go | 2 +- models/models.go | 4 +- models/publickey.go | 337 +++++++++++++++++++++++++------ models/user.go | 2 +- modules/auth/user_form.go | 4 +- modules/bindata/bindata.go | 8 +- public/css/gogs.min.css | 2 +- public/js/gogs.js | 7 + public/less/_form.less | 6 + public/less/_install.less | 3 - public/less/_repository.less | 30 +++ routers/repo/setting.go | 77 ++++++- routers/user/setting.go | 31 +-- templates/.VERSION | 2 +- templates/base/alert.tmpl | 5 + templates/repo/settings/deploy_keys.tmpl | 97 +++++++++ templates/repo/settings/nav.tmpl | 2 +- templates/repo/settings/navbar.tmpl | 19 ++ templates/user/settings/sshkeys.tmpl | 2 +- 26 files changed, 692 insertions(+), 148 deletions(-) create mode 100644 templates/repo/settings/deploy_keys.tmpl create mode 100644 templates/repo/settings/navbar.tmpl (limited to 'models/user.go') diff --git a/.gopmfile b/.gopmfile index 28bc79e6..d59b474e 100644 --- a/.gopmfile +++ b/.gopmfile @@ -10,8 +10,8 @@ github.com/Unknwon/macaron = commit:635c89ac74 github.com/Unknwon/paginater = commit:cab2d086fa github.com/codegangsta/cli = commit:2bcd11f863 github.com/go-sql-driver/mysql = commit:a197e5d405 -github.com/go-xorm/core = commit:bacc62db6e -github.com/go-xorm/xorm = commit:7b8945acfe +github.com/go-xorm/core = +github.com/go-xorm/xorm = github.com/gogits/chardet = commit:2404f77725 github.com/gogits/go-gogs-client = commit:92e76d616a github.com/lib/pq = commit:0dad96c0b9 diff --git a/cmd/serve.go b/cmd/serve.go index ecf07114..9638da8b 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -71,17 +71,17 @@ var ( } ) +func fail(userMessage, logMessage string, args ...interface{}) { + fmt.Fprintln(os.Stderr, "Gogs:", userMessage) + log.GitLogger.Fatal(3, logMessage, args...) +} + func runServ(c *cli.Context) { if c.IsSet("config") { setting.CustomConf = c.String("config") } setup("serv.log") - fail := func(userMessage, logMessage string, args ...interface{}) { - fmt.Fprintln(os.Stderr, "Gogs:", userMessage) - log.GitLogger.Fatal(3, logMessage, args...) - } - if len(c.Args()) < 1 { fail("Not enough arguments", "Not enough arguments") } @@ -131,30 +131,53 @@ func runServ(c *cli.Context) { if requestedMode == models.ACCESS_MODE_WRITE || repo.IsPrivate { keys := strings.Split(c.Args()[0], "-") if len(keys) != 2 { - fail("key-id format error", "Invalid key id: %s", c.Args()[0]) + fail("Key ID format error", "Invalid key ID: %s", c.Args()[0]) } - keyID, err = com.StrTo(keys[1]).Int64() + key, err := models.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64()) if err != nil { - fail("key-id format error", "Invalid key id: %s", err) + fail("Key ID format error", "Invalid key ID[%s]: %v", c.Args()[0], err) } + keyID = key.ID - user, err = models.GetUserByKeyId(keyID) - if err != nil { - fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err) - } + // Check deploy key or user key. + if key.Type == models.KEY_TYPE_DEPLOY { + if key.Mode < requestedMode { + fail("Key permission denied", "Cannot push with deployment key: %d", key.ID) + } + // Check if this deploy key belongs to current repository. + if !models.HasDeployKey(key.ID, repo.Id) { + fail("Key access denied", "Key access denied: %d-%d", key.ID, repo.Id) + } - mode, err := models.AccessLevel(user, repo) - if err != nil { - fail("Internal error", "Fail to check access: %v", err) - } else if mode < requestedMode { - clientMessage := _ACCESS_DENIED_MESSAGE - if mode >= models.ACCESS_MODE_READ { - clientMessage = "You do not have sufficient authorization for this action" + // Update deploy key activity. + deployKey, err := models.GetDeployKeyByRepo(key.ID, repo.Id) + if err != nil { + fail("Internal error", "GetDeployKey: %v", err) + } + + deployKey.Updated = time.Now() + if err = models.UpdateDeployKey(deployKey); err != nil { + fail("Internal error", "UpdateDeployKey: %v", err) + } + } else { + user, err = models.GetUserByKeyId(key.ID) + if err != nil { + fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err) + } + + mode, err := models.AccessLevel(user, repo) + if err != nil { + fail("Internal error", "Fail to check access: %v", err) + } else if mode < requestedMode { + clientMessage := _ACCESS_DENIED_MESSAGE + if mode >= models.ACCESS_MODE_READ { + clientMessage = "You do not have sufficient authorization for this action" + } + fail(clientMessage, + "User %s does not have level %v access to repository %s", + user.Name, requestedMode, repoPath) } - fail(clientMessage, - "User %s does not have level %v access to repository %s", - user.Name, requestedMode, repoPath) } } @@ -201,9 +224,9 @@ func runServ(c *cli.Context) { resp.Body.Close() } - // Update key activity. + // Update user key activity. if keyID > 0 { - key, err := models.GetPublicKeyById(keyID) + key, err := models.GetPublicKeyByID(keyID) if err != nil { fail("Internal error", "GetPublicKeyById: %v", err) } diff --git a/cmd/web.go b/cmd/web.go index 49e8446c..27e50cd2 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -404,6 +404,13 @@ func runWeb(ctx *cli.Context) { m.Get("/:name", repo.GitHooksEdit) m.Post("/:name", repo.GitHooksEditPost) }, middleware.GitHookService()) + + m.Group("/keys", func() { + m.Combo("").Get(repo.SettingsDeployKeys). + Post(bindIgnErr(auth.AddSSHKeyForm{}), repo.SettingsDeployKeysPost) + m.Post("/delete", repo.DeleteDeployKey) + }) + }) }, reqSignIn, middleware.RepoAssignment(true), reqRepoAdmin) diff --git a/conf/locale/locale_en-US.ini b/conf/locale/locale_en-US.ini index 98524fe7..df9927ef 100644 --- a/conf/locale/locale_en-US.ini +++ b/conf/locale/locale_en-US.ini @@ -178,7 +178,6 @@ repo_name_been_taken = Repository name has been already taken. org_name_been_taken = Organization name has been already taken. team_name_been_taken = Team name has been already taken. email_been_used = E-mail address has been already used. -ssh_key_been_used = Public key name or content has been used. illegal_team_name = Team name contains illegal characters. username_password_incorrect = Username or password is not correct. enterred_invalid_repo_name = Please make sure that the repository name you entered is correct. @@ -264,13 +263,16 @@ add_key = Add Key ssh_desc = This is a list of SSH keys associated with your account. As these keys allow anyone using them to gain access to your repositories, it is highly important that you make sure you recognize them. ssh_helper = Don't know how? Check out GitHub's guide to create your own SSH keys or solve common problems you might encounter using SSH. add_new_key = Add SSH Key +ssh_key_been_used = Public key content has been used. +ssh_key_name_used = Public key with same name has already existed. key_name = Key Name key_content = Content -add_key_success = New SSH Key has been added! +add_key_success = New SSH key '%s' has been added successfully! delete_key = Delete add_on = Added on last_used = Last used on no_activity = No recent activity +key_state_desc = This key is used in last 7 days manage_social = Manage Associated Social Accounts social_desc = This is a list of associated social accounts. Remove any binding that you do not recognize. @@ -390,7 +392,7 @@ issues.label_edit = Edit issues.label_delete = Delete issues.label_modify = Label Modification issues.label_deletion = Label Deletion -issues.label_deletion_desc = Delete label will remove its information in all related issues. Do you want to continue? +issues.label_deletion_desc = Delete this label will remove its information in all related issues. Do you want to continue? issues.label_deletion_success = Label has been deleted successfully! milestones.new = New Milestone @@ -414,7 +416,7 @@ milestones.cancel = Cancel milestones.modify = Modify Milestone milestones.edit_success = Changes of milestone '%s' has been saved successfully! milestones.deletion = Milestone Deletion -milestones.deletion_desc = Delete milestone will remove its information in all related issues. Do you want to continue? +milestones.deletion_desc = Delete this milestone will remove its information in all related issues. Do you want to continue? milestones.deletion_success = Milestone has been deleted successfully! settings = Settings @@ -422,7 +424,6 @@ settings.options = Options settings.collaboration = Collaboration settings.hooks = Webhooks settings.githooks = Git Hooks -settings.deploy_keys = Deploy Keys settings.basic_settings = Basic Settings settings.danger_zone = Danger Zone settings.site = Official Site @@ -470,6 +471,17 @@ settings.add_slack_hook_desc = Add Slack integration to your re settings.slack_token = Token settings.slack_domain = Domain settings.slack_channel = Channel +settings.deploy_keys = Deploy Keys +settings.add_deploy_key = Add Deploy Key +settings.no_deploy_keys = You haven't added any deploy key. +settings.title = Title +settings.deploy_key_content = Content +settings.key_been_used = Deploy key content has been used. +settings.key_name_used = Deploy key with same name has already existed. +settings.add_key_success = New deploy key '%s' has been added successfully! +settings.deploy_key_deletion = Delete Deploy Key +settings.deploy_key_deletion_desc = Delete this deploy key will remove all related accesses for this repository. Do you want to continue? +settings.deploy_key_deletion_success = Deploy key has been deleted successfully! diff.browse_source = Browse Source diff.parent = parent diff --git a/gogs.go b/gogs.go index 82529769..3ceb3001 100644 --- a/gogs.go +++ b/gogs.go @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.6.4.0805 Beta" +const APP_VER = "0.6.4.0806 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/error.go b/models/error.go index 38a3c053..7851e194 100644 --- a/models/error.go +++ b/models/error.go @@ -107,6 +107,82 @@ func (err ErrUserHasOrgs) Error() string { return fmt.Sprintf("user still has membership of organizations: [uid: %d]", err.UID) } +// __________ ___. .__ .__ ____ __. +// \______ \__ _\_ |__ | | |__| ____ | |/ _|____ ___.__. +// | ___/ | \ __ \| | | |/ ___\ | <_/ __ < | | +// | | | | / \_\ \ |_| \ \___ | | \ ___/\___ | +// |____| |____/|___ /____/__|\___ > |____|__ \___ > ____| +// \/ \/ \/ \/\/ + +type ErrKeyNotExist struct { + ID int64 +} + +func IsErrKeyNotExist(err error) bool { + _, ok := err.(ErrKeyNotExist) + return ok +} + +func (err ErrKeyNotExist) Error() string { + return fmt.Sprintf("public key does not exist: [id: %d]", err.ID) +} + +type ErrKeyAlreadyExist struct { + OwnerID int64 + Content string +} + +func IsErrKeyAlreadyExist(err error) bool { + _, ok := err.(ErrKeyAlreadyExist) + return ok +} + +func (err ErrKeyAlreadyExist) Error() string { + return fmt.Sprintf("public key already exists: [owner_id: %d, content: %s]", err.OwnerID, err.Content) +} + +type ErrKeyNameAlreadyUsed struct { + OwnerID int64 + Name string +} + +func IsErrKeyNameAlreadyUsed(err error) bool { + _, ok := err.(ErrKeyNameAlreadyUsed) + return ok +} + +func (err ErrKeyNameAlreadyUsed) Error() string { + return fmt.Sprintf("public key already exists: [owner_id: %d, name: %s]", err.OwnerID, err.Name) +} + +type ErrDeployKeyAlreadyExist struct { + KeyID int64 + RepoID int64 +} + +func IsErrDeployKeyAlreadyExist(err error) bool { + _, ok := err.(ErrDeployKeyAlreadyExist) + return ok +} + +func (err ErrDeployKeyAlreadyExist) Error() string { + return fmt.Sprintf("public key already exists: [key_id: %d, repo_id: %d]", err.KeyID, err.RepoID) +} + +type ErrDeployKeyNameAlreadyUsed struct { + RepoID int64 + Name string +} + +func IsErrDeployKeyNameAlreadyUsed(err error) bool { + _, ok := err.(ErrDeployKeyNameAlreadyUsed) + return ok +} + +func (err ErrDeployKeyNameAlreadyUsed) Error() string { + return fmt.Sprintf("public key already exists: [repo_id: %d, name: %s]", err.RepoID, err.Name) +} + // ________ .__ __ .__ // \_____ \_______ _________ ____ |__|____________ _/ |_|__| ____ ____ // / | \_ __ \/ ___\__ \ / \| \___ /\__ \\ __\ |/ _ \ / \ diff --git a/models/issue.go b/models/issue.go index 80afb415..a80a9849 100644 --- a/models/issue.go +++ b/models/issue.go @@ -56,16 +56,11 @@ type Issue struct { Updated time.Time `xorm:"UPDATED"` } -func (i *Issue) BeforeSet(colName string, val xorm.Cell) { +func (i *Issue) AfterSet(colName string, _ xorm.Cell) { var err error switch colName { case "milestone_id": - mid := (*val).(int64) - if mid <= 0 { - return - } - - i.Milestone, err = GetMilestoneById(mid) + i.Milestone, err = GetMilestoneById(i.MilestoneID) if err != nil { log.Error(3, "GetMilestoneById: %v", err) } @@ -664,15 +659,14 @@ type Milestone struct { ClosedDate time.Time } -func (m *Milestone) BeforeSet(colName string, val xorm.Cell) { +func (m *Milestone) AfterSet(colName string, _ xorm.Cell) { if colName == "deadline" { - t := (*val).(time.Time) - if t.Year() == 9999 { + if m.Deadline.Year() == 9999 { return } - m.DeadlineString = t.Format("2006-01-02") - if time.Now().After(t) { + m.DeadlineString = m.Deadline.Format("2006-01-02") + if time.Now().After(m.Deadline) { m.IsOverDue = true } } diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 156fceda..c7900743 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -57,7 +57,7 @@ var migrations = []Migration{ NewMigration("refactor access table to use id's", accessRefactor), // V2 -> V3:v0.5.13 NewMigration("generate team-repo from team", teamToTeamRepo), // V3 -> V4:v0.5.13 NewMigration("fix locale file load panic", fixLocaleFileLoadPanic), // V4 -> V5:v0.6.0 - NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix), // V5 -> V6:v0.6.3 // V4 -> V5:v0.6.0 + NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix), // V5 -> V6:v0.6.3 } // Migrate database to current version diff --git a/models/models.go b/models/models.go index a10a48f3..01b96c0f 100644 --- a/models/models.go +++ b/models/models.go @@ -55,7 +55,7 @@ var ( func init() { tables = append(tables, new(User), new(PublicKey), new(Oauth2), new(AccessToken), - new(Repository), new(Collaboration), new(Access), + new(Repository), new(DeployKey), new(Collaboration), new(Access), new(Watch), new(Star), new(Follow), new(Action), new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone), new(Mirror), new(Release), new(LoginSource), new(Webhook), @@ -132,7 +132,7 @@ func NewTestEngine(x *xorm.Engine) (err error) { func SetEngine() (err error) { x, err = getEngine() if err != nil { - return fmt.Errorf("Connect to database: %v", err) + return fmt.Errorf("Fail to connect to database: %v", err) } x.SetMapper(core.GonicMapper{}) diff --git a/models/publickey.go b/models/publickey.go index 0db9f333..67891fba 100644 --- a/models/publickey.go +++ b/models/publickey.go @@ -21,6 +21,7 @@ import ( "time" "github.com/Unknwon/com" + "github.com/go-xorm/xorm" "github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/process" @@ -33,8 +34,6 @@ const ( ) var ( - ErrKeyAlreadyExist = errors.New("Public key already exists") - ErrKeyNotExist = errors.New("Public key does not exist") ErrKeyUnableVerify = errors.New("Unable to verify public key") ) @@ -78,17 +77,34 @@ func init() { } } -// PublicKey represents a SSH key. +type KeyType int + +const ( + KEY_TYPE_USER = iota + 1 + KEY_TYPE_DEPLOY +) + +// PublicKey represents a SSH or deploy key. type PublicKey struct { - Id int64 - OwnerId int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` - Name string `xorm:"UNIQUE(s) NOT NULL"` - Fingerprint string `xorm:"INDEX NOT NULL"` - Content string `xorm:"TEXT NOT NULL"` - Created time.Time `xorm:"CREATED"` - Updated time.Time - HasRecentActivity bool `xorm:"-"` - HasUsed bool `xorm:"-"` + ID int64 `xorm:"pk autoincr"` + OwnerID int64 `xorm:"INDEX NOT NULL"` + Name string `xorm:"NOT NULL"` + Fingerprint string `xorm:"NOT NULL"` + Content string `xorm:"UNIQUE TEXT NOT NULL"` + Mode AccessMode `xorm:"NOT NULL DEFAULT 2"` + Type KeyType `xorm:"NOT NULL DEFAULT 1"` + Created time.Time `xorm:"CREATED"` + Updated time.Time // Note: Updated must below Created for AfterSet. + HasRecentActivity bool `xorm:"-"` + HasUsed bool `xorm:"-"` +} + +func (k *PublicKey) AfterSet(colName string, _ xorm.Cell) { + switch colName { + case "created": + k.HasUsed = k.Updated.After(k.Created) + k.HasRecentActivity = k.Updated.Add(7 * 24 * time.Hour).After(time.Now()) + } } // OmitEmail returns content of public key but without e-mail address. @@ -98,7 +114,7 @@ func (k *PublicKey) OmitEmail() string { // GetAuthorizedString generates and returns formatted public key string for authorized_keys file. func (key *PublicKey) GetAuthorizedString() string { - return fmt.Sprintf(_TPL_PUBLICK_KEY, appPath, key.Id, setting.CustomConf, key.Content) + return fmt.Sprintf(_TPL_PUBLICK_KEY, appPath, key.ID, setting.CustomConf, key.Content) } var minimumKeySizes = map[string]int{ @@ -126,8 +142,8 @@ func extractTypeFromBase64Key(key string) (string, error) { return string(b[4 : 4+keyLength]), nil } -// Parse any key string in openssh or ssh2 format to clean openssh string (rfc4253) -func ParseKeyString(content string) (string, error) { +// parseKeyString parses any key string in openssh or ssh2 format to clean openssh string (rfc4253) +func parseKeyString(content string) (string, error) { // Transform all legal line endings to a single "\n" s := strings.Replace(strings.Replace(strings.TrimSpace(content), "\r\n", "\n", -1), "\r", "\n", -1) @@ -190,16 +206,21 @@ func ParseKeyString(content string) (string, error) { } // CheckPublicKeyString checks if the given public key string is recognized by SSH. -func CheckPublicKeyString(content string) (bool, error) { +func CheckPublicKeyString(content string) (_ string, err error) { + content, err = parseKeyString(content) + if err != nil { + return "", err + } + content = strings.TrimRight(content, "\n\r") if strings.ContainsAny(content, "\n\r") { - return false, errors.New("only a single line with a single key please") + return "", errors.New("only a single line with a single key please") } // write the key to a file… tmpFile, err := ioutil.TempFile(os.TempDir(), "keytest") if err != nil { - return false, err + return "", err } tmpPath := tmpFile.Name() defer os.Remove(tmpPath) @@ -209,37 +230,36 @@ func CheckPublicKeyString(content string) (bool, error) { // Check if ssh-keygen recognizes its contents. stdout, stderr, err := process.Exec("CheckPublicKeyString", "ssh-keygen", "-l", "-f", tmpPath) if err != nil { - return false, errors.New("ssh-keygen -l -f: " + stderr) + return "", errors.New("ssh-keygen -l -f: " + stderr) } else if len(stdout) < 2 { - return false, errors.New("ssh-keygen returned not enough output to evaluate the key: " + stdout) + return "", errors.New("ssh-keygen returned not enough output to evaluate the key: " + stdout) } // The ssh-keygen in Windows does not print key type, so no need go further. if setting.IsWindows { - return true, nil + return content, nil } - fmt.Println(stdout) sshKeygenOutput := strings.Split(stdout, " ") if len(sshKeygenOutput) < 4 { - return false, ErrKeyUnableVerify + return content, ErrKeyUnableVerify } // Check if key type and key size match. if !setting.Service.DisableMinimumKeySizeCheck { keySize := com.StrTo(sshKeygenOutput[0]).MustInt() if keySize == 0 { - return false, errors.New("cannot get key size of the given key") + return "", errors.New("cannot get key size of the given key") } keyType := strings.TrimSpace(sshKeygenOutput[len(sshKeygenOutput)-1]) if minimumKeySize := minimumKeySizes[keyType]; minimumKeySize == 0 { - return false, errors.New("sorry, unrecognized public key type") + return "", errors.New("sorry, unrecognized public key type") } else if keySize < minimumKeySize { - return false, fmt.Errorf("the minimum accepted size of a public key %s is %d", keyType, minimumKeySize) + return "", fmt.Errorf("the minimum accepted size of a public key %s is %d", keyType, minimumKeySize) } } - return true, nil + return content, nil } // saveAuthorizedKeyFile writes SSH key content to authorized_keys file. @@ -278,20 +298,23 @@ func saveAuthorizedKeyFile(keys ...*PublicKey) error { return nil } -// AddPublicKey adds new public key to database and authorized_keys file. -func AddPublicKey(key *PublicKey) (err error) { - has, err := x.Get(key) +func checkKeyContent(content string) error { + // Same key can only be added once. + has, err := x.Where("content=?", content).Get(new(PublicKey)) if err != nil { return err } else if has { - return ErrKeyAlreadyExist + return ErrKeyAlreadyExist{0, content} } + return nil +} +func addKey(e Engine, key *PublicKey) (err error) { // Calculate fingerprint. tmpPath := strings.Replace(path.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()), "id_rsa.pub"), "\\", "/", -1) os.MkdirAll(path.Dir(tmpPath), os.ModePerm) - if err = ioutil.WriteFile(tmpPath, []byte(key.Content), os.ModePerm); err != nil { + if err = ioutil.WriteFile(tmpPath, []byte(key.Content), 0644); err != nil { return err } stdout, stderr, err := process.Exec("AddPublicKey", "ssh-keygen", "-l", "-f", tmpPath) @@ -301,32 +324,56 @@ func AddPublicKey(key *PublicKey) (err error) { return errors.New("not enough output for calculating fingerprint: " + stdout) } key.Fingerprint = strings.Split(stdout, " ")[1] - if has, err := x.Get(&PublicKey{Fingerprint: key.Fingerprint}); err == nil && has { - return ErrKeyAlreadyExist - } // Save SSH key. - if _, err = x.Insert(key); err != nil { + if _, err = e.Insert(key); err != nil { return err - } else if err = saveAuthorizedKeyFile(key); err != nil { - // Roll back. - if _, err2 := x.Delete(key); err2 != nil { - return err2 - } + } + return saveAuthorizedKeyFile(key) +} + +// AddPublicKey adds new public key to database and authorized_keys file. +func AddPublicKey(ownerID int64, name, content string) (err error) { + if err = checkKeyContent(content); err != nil { return err } - return nil + // Key name of same user cannot be duplicated. + has, err := x.Where("owner_id=? AND name=?", ownerID, name).Get(new(PublicKey)) + if err != nil { + return err + } else if has { + return ErrKeyNameAlreadyUsed{ownerID, name} + } + + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + key := &PublicKey{ + OwnerID: ownerID, + Name: name, + Content: content, + Mode: ACCESS_MODE_WRITE, + Type: KEY_TYPE_USER, + } + if err = addKey(sess, key); err != nil { + return fmt.Errorf("addKey: %v", err) + } + + return sess.Commit() } -// GetPublicKeyById returns public key by given ID. -func GetPublicKeyById(keyId int64) (*PublicKey, error) { +// GetPublicKeyByID returns public key by given ID. +func GetPublicKeyByID(keyID int64) (*PublicKey, error) { key := new(PublicKey) - has, err := x.Id(keyId).Get(key) + has, err := x.Id(keyID).Get(key) if err != nil { return nil, err } else if !has { - return nil, ErrKeyNotExist + return nil, ErrKeyNotExist{keyID} } return key, nil } @@ -334,16 +381,7 @@ func GetPublicKeyById(keyId int64) (*PublicKey, error) { // ListPublicKeys returns a list of public keys belongs to given user. func ListPublicKeys(uid int64) ([]*PublicKey, error) { keys := make([]*PublicKey, 0, 5) - err := x.Where("owner_id=?", uid).Find(&keys) - if err != nil { - return nil, err - } - - for _, key := range keys { - key.HasUsed = key.Updated.After(key.Created) - key.HasRecentActivity = key.Updated.Add(7 * 24 * time.Hour).After(time.Now()) - } - return keys, nil + return keys, x.Where("owner_id=?", uid).Find(&keys) } // rewriteAuthorizedKeys finds and deletes corresponding line in authorized_keys file. @@ -364,7 +402,7 @@ func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error { defer fw.Close() isFound := false - keyword := fmt.Sprintf("key-%d", key.Id) + keyword := fmt.Sprintf("key-%d", key.ID) buf := bufio.NewReader(fr) for { line, errRead := buf.ReadString('\n') @@ -401,20 +439,19 @@ func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error { // UpdatePublicKey updates given public key. func UpdatePublicKey(key *PublicKey) error { - _, err := x.Id(key.Id).AllCols().Update(key) + _, err := x.Id(key.ID).AllCols().Update(key) return err } -// DeletePublicKey deletes SSH key information both in database and authorized_keys file. -func DeletePublicKey(key *PublicKey) error { - has, err := x.Get(key) +func deletePublicKey(e *xorm.Session, key *PublicKey) error { + has, err := e.Get(key) if err != nil { return err } else if !has { - return ErrKeyNotExist + return nil } - if _, err = x.Delete(key); err != nil { + if _, err = e.Id(key.ID).Delete(key); err != nil { return err } @@ -428,6 +465,21 @@ func DeletePublicKey(key *PublicKey) error { return os.Rename(tmpPath, fpath) } +// DeletePublicKey deletes SSH key information both in database and authorized_keys file. +func DeletePublicKey(key *PublicKey) (err error) { + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + if err = deletePublicKey(sess, key); err != nil { + return err + } + + return sess.Commit() +} + // RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again. func RewriteAllPublicKeys() error { sshOpLocker.Lock() @@ -461,3 +513,162 @@ func RewriteAllPublicKeys() error { return nil } + +// ________ .__ ____ __. +// \______ \ ____ ______ | | ____ ___.__.| |/ _|____ ___.__. +// | | \_/ __ \\____ \| | / _ < | || <_/ __ < | | +// | ` \ ___/| |_> > |_( <_> )___ || | \ ___/\___ | +// /_______ /\___ > __/|____/\____// ____||____|__ \___ > ____| +// \/ \/|__| \/ \/ \/\/ + +// DeployKey represents deploy key information and its relation with repository. +type DeployKey struct { + ID int64 `xorm:"pk autoincr"` + KeyID int64 `xorm:"UNIQUE(s) INDEX"` + RepoID int64 `xorm:"UNIQUE(s) INDEX"` + Name string + Fingerprint string + Created time.Time `xorm:"CREATED"` + Updated time.Time // Note: Updated must below Created for AfterSet. + HasRecentActivity bool `xorm:"-"` + HasUsed bool `xorm:"-"` +} + +func (k *DeployKey) AfterSet(colName string, _ xorm.Cell) { + switch colName { + case "created": + k.HasUsed = k.Updated.After(k.Created) + k.HasRecentActivity = k.Updated.Add(7 * 24 * time.Hour).After(time.Now()) + } +} + +func checkDeployKey(e Engine, keyID, repoID int64, name string) error { + // Note: We want error detail, not just true or false here. + has, err := e.Where("key_id=? AND repo_id=?", keyID, repoID).Get(new(DeployKey)) + if err != nil { + return err + } else if has { + return ErrDeployKeyAlreadyExist{keyID, repoID} + } + + has, err = e.Where("repo_id=? AND name=?", repoID, name).Get(new(DeployKey)) + if err != nil { + return err + } else if has { + return ErrDeployKeyNameAlreadyUsed{repoID, name} + } + + return nil +} + +// addDeployKey adds new key-repo relation. +func addDeployKey(e *xorm.Session, keyID, repoID int64, name, fingerprint string) (err error) { + if err = checkDeployKey(e, keyID, repoID, name); err != nil { + return err + } + + _, err = e.Insert(&DeployKey{ + KeyID: keyID, + RepoID: repoID, + Name: name, + Fingerprint: fingerprint, + }) + return err +} + +// HasDeployKey returns true if public key is a deploy key of given repository. +func HasDeployKey(keyID, repoID int64) bool { + has, _ := x.Where("key_id=? AND repo_id=?", keyID, repoID).Get(new(DeployKey)) + return has +} + +// AddDeployKey add new deploy key to database and authorized_keys file. +func AddDeployKey(repoID int64, name, content string) (err error) { + if err = checkKeyContent(content); err != nil { + return err + } + + key := &PublicKey{ + Content: content, + Mode: ACCESS_MODE_READ, + Type: KEY_TYPE_DEPLOY, + } + has, err := x.Get(key) + if err != nil { + return err + } + + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + // First time use this deploy key. + if !has { + if err = addKey(sess, key); err != nil { + return nil + } + } + + if err = addDeployKey(sess, key.ID, repoID, name, key.Fingerprint); err != nil { + return err + } + + return sess.Commit() +} + +// GetDeployKeyByRepo returns deploy key by given public key ID and repository ID. +func GetDeployKeyByRepo(keyID, repoID int64) (*DeployKey, error) { + key := &DeployKey{ + KeyID: keyID, + RepoID: repoID, + } + _, err := x.Get(key) + return key, err +} + +// UpdateDeployKey updates deploy key information. +func UpdateDeployKey(key *DeployKey) error { + _, err := x.Id(key.ID).AllCols().Update(key) + return err +} + +// DeleteDeployKey deletes deploy key from its repository authorized_keys file if needed. +func DeleteDeployKey(id int64) error { + key := &DeployKey{ID: id} + has, err := x.Id(key.ID).Get(key) + if err != nil { + return err + } else if !has { + return nil + } + + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + if _, err = sess.Id(key.ID).Delete(key); err != nil { + return fmt.Errorf("delete deploy key[%d]: %v", key.ID, err) + } + + // Check if this is the last reference to same key content. + has, err = sess.Where("key_id=?", key.KeyID).Get(new(DeployKey)) + if err != nil { + return err + } else if !has { + if err = deletePublicKey(sess, &PublicKey{ID: key.KeyID}); err != nil { + return err + } + } + + return sess.Commit() +} + +// ListDeployKeys returns all deploy keys by given repository ID. +func ListDeployKeys(repoID int64) ([]*DeployKey, error) { + keys := make([]*DeployKey, 0, 5) + return keys, x.Where("repo_id=?", repoID).Find(&keys) +} diff --git a/models/user.go b/models/user.go index 4b6517d7..1e514cdf 100644 --- a/models/user.go +++ b/models/user.go @@ -505,7 +505,7 @@ func DeleteUser(u *User) error { // Delete all SSH keys. keys := make([]*PublicKey, 0, 10) - if err = sess.Find(&keys, &PublicKey{OwnerId: u.Id}); err != nil { + if err = sess.Find(&keys, &PublicKey{OwnerID: u.Id}); err != nil { return err } for _, key := range keys { diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go index c2dc8541..0d6987ad 100644 --- a/modules/auth/user_form.go +++ b/modules/auth/user_form.go @@ -126,8 +126,8 @@ func (f *ChangePasswordForm) Validate(ctx *macaron.Context, errs binding.Errors) } type AddSSHKeyForm struct { - SSHTitle string `form:"title" binding:"Required"` - Content string `form:"content" binding:"Required"` + Title string `binding:"Required;MaxSize(50)"` + Content string `binding:"Required"` } func (f *AddSSHKeyForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { diff --git a/modules/bindata/bindata.go b/modules/bindata/bindata.go index bf28bb9a..ed8407a8 100644 --- a/modules/bindata/bindata.go +++ b/modules/bindata/bindata.go @@ -127,7 +127,7 @@ func confAppIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/app.ini", size: 9185, mode: os.FileMode(420), modTime: time.Unix(1438777611, 0)} + info := bindataFileInfo{name: "conf/app.ini", size: 9185, mode: os.FileMode(420), modTime: time.Unix(1438834795, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -772,7 +772,7 @@ func confLocaleLocale_deDeIni() (*asset, error) { return a, nil } -var _confLocaleLocale_enUsIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xc4\x7d\xdb\x72\x1c\x47\xd2\xde\x7d\x3f\x45\x4b\x0e\x9a\x52\x04\x38\x0c\x49\x61\x87\x43\x41\x52\x86\x00\xf1\xb0\x3f\x41\xf0\x27\xc0\x5d\xaf\x19\x8c\xde\x9e\xe9\xc6\x4c\x2f\x66\xba\x47\x7d\xc0\x08\x7b\xe5\xd7\xf0\xeb\xf9\x49\x9c\xf9\x65\x66\x1d\xba\x7b\x40\x69\xff\x0d\xfb\x06\xa8\xa9\xca\x3a\x65\x65\x65\xe5\xa9\xaa\xf3\xfd\x3e\x2b\xca\x6e\x95\x3e\x4f\x4f\xd3\x7d\x5e\xd5\xdb\xb2\xeb\xd2\xae\xdc\xde\x3c\xd9\x34\x5d\x5f\x16\xe9\xab\xaa\xa7\xdf\xed\x5d\xb5\x2a\x93\x64\xd3\xec\x4a\x02\x7d\x4d\xff\x92\x22\xef\x36\xcb\x26\x6f\x0b\xca\x38\xb7\x74\x52\xfe\xb6\xdf\x36\x2d\x03\xfd\x22\xa9\x64\x53\x6e\xf7\x5c\x87\xfe\x25\x5d\xb5\xae\xb3\xaa\xa6\x9f\x57\x94\x4a\xdf\xd4\x49\xd7\xac\xaa\x7c\x9b\x05\x05\xc8\xb0\xf2\x1f\xd3\xef\xeb\x22\xbd\xea\xcb\x7d\xfa\xac\xdb\xe5\xdb\xed\x8b\xbc\x43\x95\xbe\x4c\xf3\xd5\xaa\x19\xea\xfe\xd9\x53\x29\x90\xc6\x9b\xa1\xb7\xd6\x2f\x87\x5e\xf2\x86\xbd\x65\x7d\xdc\x27\x6d\xb9\xae\x68\x62\x2d\x65\x7d\xd0\x64\x72\x28\x97\x5d\xd5\xf3\xa0\xff\x22\xa9\xe4\xae\x6c\xbb\xaa\xe1\xf1\xfc\x59\x52\xc9\x3e\x5f\x33\xc0\x7b\xfa\x97\xf4\xe5\x6e\xbf\xcd\x51\xe1\x5a\x93\xc9\x36\xaf\xd7\x83\xc0\xbc\xd5\x64\x92\x0c\x84\xb9\x3a\x07\xce\x3e\x6a\x32\x29\x77\x79\xb5\x65\xfc\x3c\xe1\x04\xb5\xdb\x75\x87\x06\x58\x7c\xaf\x49\x1a\x63\xd6\xdf\xef\x4b\x0c\xf1\xc9\x35\xa5\x92\x55\xbe\xef\x57\x9b\x9c\x72\xce\x24\x95\x10\xd0\xbe\xa1\xb1\x36\xed\x3d\xe0\xec\x47\xd2\xb4\xeb\xbc\xae\xfe\x91\xf7\x32\xfe\xcb\xe0\x67\xb2\xab\xda\xb6\xe1\xa9\x5f\x20\x91\xd4\xe5\x21\xe3\x76\x28\xe7\x5d\x79\x08\x5b\xe1\x92\x5d\xb5\x6e\x65\x96\x5c\x78\x81\x5f\xdc\x0a\x97\xdd\x34\xed\xad\x16\xbc\xe4\xe4\xa8\x2a\x0d\x42\x4b\xe3\xfe\xf3\x9a\xf0\xa2\xa5\x17\xf8\x11\x01\x74\x49\x5e\xec\xaa\x3a\xdb\xe7\x75\xc9\x38\x3a\xe5\x5f\x84\x17\xfa\x95\xe8\x72\x67\x5d\xd9\xf7\x55\xbd\xee\xb8\x58\xb2\xd2\x2b\xcd\x4a\x82\x32\x97\xc7\xe3\xe9\xb2\x9b\xb2\x2c\x64\x44\x5d\xfa\x92\xd2\xc9\x7e\xd8\x6e\x69\xee\xbf\x0e\x65\xd7\x33\xfc\x7b\xfa\x4d\xb3\x90\xdf\x49\xd5\x75\x94\xa0\xec\x37\x48\x24\xb4\x00\xf5\x0a\x43\x3a\x43\x22\x49\x3e\x75\x65\xde\xae\x36\x9f\x13\xf9\x8f\x1e\x39\xb1\x58\x2c\x8e\x2e\x0d\x93\x83\x92\x82\xf4\x60\x1d\x24\xab\xa6\xe0\x1f\x67\xf4\x8f\x9a\xae\xea\xae\x27\x92\xfe\x9c\x68\x82\xc1\x24\x25\x68\xec\xab\x7e\x5b\xfa\x4c\xec\x8f\x8e\xd7\x21\x7d\x59\xb5\x5d\xff\xa4\xaf\x88\xe4\x3e\x0c\x75\xc2\xf3\x23\x72\xce\x8a\xa5\xed\xf2\x57\x0d\x61\x07\xd9\x2d\xcd\xef\xe2\xfe\xea\xdf\xdf\x9e\xa4\xef\x69\xab\xaf\xdb\x92\xd2\x29\xb5\x41\xff\xa8\xce\x0f\x8b\x84\x6a\x59\x4f\xe7\x79\x9f\x2f\xf3\xae\xf4\x68\xe5\x42\xa1\x51\x57\x06\x4a\x65\xb6\x01\x16\xd1\xf5\xd1\x7c\xe7\xe8\x9c\xda\xd0\xdd\xe1\xda\x78\xc7\x5b\x84\xf2\x99\x6b\xa0\xf2\xfb\x6d\xc9\xf9\xd4\x54\xfa\xe6\xdd\xbb\xcb\xf3\x9f\xd3\xb2\x5e\x57\x75\x99\x1e\xaa\x7e\x93\x0e\xfd\xcd\x7f\xcb\xd6\x65\x5d\xb6\xc4\x44\x56\x55\x4a\x3b\xa3\x25\x22\x48\x89\x3c\x65\x72\x8b\xa4\xeb\xb6\xd9\x4e\xd0\x7b\x75\xf5\x36\xbd\x60\x14\xef\xf3\x7e\x83\x81\xf4\x9b\xa4\xfb\x75\xcb\x28\x72\x1d\x5e\x6f\xca\xf4\xa6\xa2\x59\x03\xa8\xb9\x31\x7c\xa4\x85\x8e\x71\x91\x94\x6d\x9b\xd1\xbe\xef\xef\x33\xad\xac\xed\x8d\x21\xa5\x09\x22\x9d\xba\xe9\xd3\x65\x99\xa2\xce\x22\x49\x6c\xc0\x86\xdd\xd3\xfd\x7e\x5b\xad\x64\xc7\xbe\x92\x32\x8f\x68\x66\xd1\x8a\xa5\x10\x0e\x88\xb2\xb2\x00\x5d\xc4\xff\xee\x9b\xa1\x4d\x23\x36\x80\xfa\x9b\x92\xf8\xf2\x66\xa0\x2d\x97\x13\x4f\xdd\x36\x43\xf1\x15\x28\xd5\x46\xef\x09\x35\xfd\xd0\xd0\x80\x81\x1d\x07\xe0\xbb\x38\x25\x8a\xe3\x53\xa1\x2d\x77\x0d\x71\x07\x47\xec\x15\x11\xd4\xa1\xa2\x42\x9a\x69\x97\xdf\xd1\x7e\xeb\x9b\xb4\xdf\x54\x5d\x5a\x10\xb1\xad\xb8\x61\xda\x1a\x03\xf1\x63\x21\x0b\x22\x50\x21\x0d\xcb\x8b\xd7\x00\x50\xbb\x81\xa8\x69\x43\x8d\x31\xb7\xe7\xa3\x89\x9a\x9c\x1b\x27\xa6\x44\xed\x80\xbe\x89\x72\x1b\xe2\xad\xcc\xfd\xce\x91\xd0\xdf\x61\xfb\x34\xaa\xfc\xe6\x86\x46\xd5\x11\x55\xbc\x4e\x57\xdb\x86\x48\xea\xe3\x87\xb7\x54\x79\xd3\xf7\xfb\x6c\xdf\xb4\x20\xe3\xeb\xeb\xf7\xb4\x3d\xda\xde\xe7\x06\xb8\x66\x98\x7a\xd8\x2d\xe9\xd7\x61\x53\x11\x13\xc8\x83\x05\x02\x2a\xb6\x7c\xc0\xd4\x69\x53\x2f\xb0\x56\x43\xbb\x1d\x2d\x23\x75\x69\x25\x47\x86\xc7\x43\x78\xca\x7f\xae\xfc\x28\x31\xdd\x8e\x4e\xe1\x03\x16\x95\xa6\x5a\xe2\x34\x21\xda\x6a\xf6\xdc\x6e\x40\x5c\x97\x9a\xe1\x29\x0a\x27\x90\x2b\x97\x73\x88\x4a\x71\xc6\x07\xbc\x74\x47\x13\xd6\xdd\x7c\x75\x41\x68\xc0\x96\x46\xee\x4d\xdb\xec\x28\xf7\x25\xfd\xf3\x19\x7e\xf8\x17\xdc\x1e\x60\xf2\xa2\x20\x36\xd3\x9d\xa4\x1f\x5e\x9e\xa5\xff\xe5\x87\xef\xbf\x5f\xa4\x6f\x7a\xde\x10\x4c\x23\x7f\xe7\xb5\xa5\xa4\x1c\x88\x0e\x94\x76\x6e\x4f\xcb\xff\x35\x13\xf8\xd7\xe9\x33\x94\xfe\xf7\xf2\xb7\x9c\xce\xd9\x72\xb1\x6a\x76\x2f\x78\x73\xef\xf2\x7e\x91\x70\x09\x51\x8d\x92\xd3\x55\x59\x17\x94\xd0\x63\x55\xcb\x02\xae\xa3\xe5\xc1\x21\x2b\xa7\x7f\xb6\x6a\xea\x9b\xaa\xe5\x09\xfd\x52\xe7\x4b\xc2\x89\xc9\x05\xc4\x8e\x51\x62\x67\x17\x21\x8d\x36\x72\x75\x73\xef\x41\x31\xd5\x77\x9c\xa9\x0b\x9a\xb0\xac\x44\x8d\xaa\xc8\xe4\xb0\x7c\x85\x6c\xac\xdb\x25\x4d\xaf\x35\x7c\x77\x1e\xe1\xcd\xcd\xcd\x96\x18\x9b\x31\x2b\xed\xe1\x52\x72\x85\x6f\x85\x20\x44\x8c\x7b\x48\x36\xe7\x55\x07\xc8\xb3\xf3\x77\x69\x79\x47\xd4\x46\xe4\xb0\x6f\x9b\x62\x58\x81\xc2\x18\xf6\x24\xe5\x63\x82\xf0\x4b\x9c\x61\x25\xec\x2d\xd8\xab\x3c\x34\x66\x08\x2b\x02\xa2\x2d\x5a\x48\x7b\x99\x20\xa8\x35\x41\xc2\xba\xb9\x62\xe1\x30\x2c\x9b\xad\x30\x19\x1d\x56\xa9\x1b\xd7\xa5\xe5\xae\xb7\xf7\x29\x4e\x7d\xd0\xc5\xaa\x2d\x03\xd9\xae\x5b\x24\x7a\x56\x99\x84\x98\xdd\x55\x24\x54\x04\x4b\x85\x52\x13\x17\x99\x3d\xfc\x99\x01\x58\x4c\xeb\x66\xeb\xba\x81\x5d\x72\xc7\x5c\x42\x73\xa7\xce\x79\x7c\x1d\x86\x80\x1e\x58\xdc\x23\x62\xbc\xab\xc0\x69\x14\x59\x18\x2b\x61\x0c\x5d\x53\x57\x5d\x59\xa2\x05\xaa\xff\x94\xda\x44\x9d\x85\x8a\x30\x2a\x8a\xd8\xb9\xfb\xd7\x66\x48\x8b\x26\xe5\x83\x00\xec\x8c\x6a\xdb\x54\x6b\x9d\xbe\xce\x39\x6d\xab\xf5\x86\xf8\x4a\x73\x38\x11\xa4\x1d\x36\x4d\xc9\xb4\xf3\xe6\xfc\xf9\x77\x32\x8e\x35\x33\x37\x57\x89\xd9\x62\x3e\xf4\x0d\xd3\xa9\x2e\xa1\x0c\xc1\x1d\x2f\x80\x9c\x08\x4b\x02\x34\x16\x4f\x4d\x00\x9b\x9e\xd6\xba\x4f\xc2\x32\xdd\x20\x1e\x46\x6a\x8f\x44\x5c\x95\x62\xb2\x75\x03\xc9\xcc\xa4\x16\x66\xd5\x24\x4a\x77\x7d\xb6\xae\xfa\xec\x86\x37\x2c\xb7\xf9\x92\xeb\xf2\xc9\x41\x25\xe9\x63\x2a\x7a\x9c\xd2\xae\x27\xc9\xb1\xf8\x31\x7d\x74\xa7\xc7\xf5\x0f\xbc\x13\xb3\xfc\x8e\x60\xb1\x18\x40\x70\x4b\x14\x2e\xd2\x82\x89\xef\x45\x43\x74\xce\x38\xef\x86\x3d\x38\xba\x9e\xd0\x27\xe9\x5e\x00\x8b\xe6\x50\x6f\x9b\xbc\x00\xcb\xa1\xdd\x55\x41\xf9\x58\x56\x75\x4e\xa7\x8b\xb5\x02\x56\xf6\x88\xa8\xe1\xdd\xe5\x35\x00\xd7\xcd\x72\xa8\xb6\x85\x01\x2c\x68\x86\x77\xf9\xb6\x2a\x58\xce\xd2\x75\x0f\x65\x1a\xcb\xaa\x64\x2c\xab\xa6\xe5\xe3\x10\xb3\xb1\x8a\x47\xce\xe1\x96\xcf\x37\x64\x53\x5d\x85\x45\x3d\x77\x64\x32\x1a\x68\xe1\x21\x80\xf2\x81\x0a\x8a\xa9\xba\xfa\x71\x8f\x91\xae\x06\xea\x8b\x16\x9d\xb3\xa9\x62\x97\x3e\x79\x41\x7f\x13\x3e\x9e\x85\xef\xad\xa7\x88\xe7\xc2\x54\x0a\x07\xd9\xa5\xd1\x50\x23\xf2\x76\xd4\x65\xc4\x1b\xcc\x35\x1c\xaf\x91\x40\x37\x08\xbd\xb2\xa6\xb5\xa5\x65\x2d\xbf\xa2\xc4\x63\xda\xc0\xeb\x2d\x16\x21\x87\xf4\x42\x62\x5c\x43\x78\x63\x02\x39\x91\xed\x72\x43\x53\x63\xde\xd9\xe7\xb7\x34\xb6\xbc\x25\x21\x2c\xf9\xc4\xda\xe8\xe7\x64\x10\x01\xa8\xd9\x16\x4e\xd8\x04\x4d\x37\xed\x58\xc5\xf2\x40\x8e\x5e\x3b\x92\x22\x57\x9b\xcc\xe9\xb2\x8c\x94\xbe\xfc\x0d\x67\x1e\x8a\xbc\x6a\xcb\xc4\xce\x45\xc9\xee\x1e\xcb\xc5\x93\xb8\xb8\xf7\xab\x45\xe2\x0f\x6d\x11\x12\xd1\x97\x0d\x63\xed\xae\x74\x50\x67\x61\x6e\x5c\x81\xda\x22\x41\x4d\x9b\x8a\x35\x21\x2a\x12\x75\x4d\x4b\x45\x65\x23\x55\xe4\x93\xea\xd8\x9f\x13\xeb\x20\x6a\x32\xf9\x44\xcc\x80\xf4\x12\x61\x2f\x19\x6b\x63\xb6\x38\x34\x14\xe1\x39\xac\x98\x29\x3f\xf0\xe7\xe0\xa6\xdc\xf3\x91\xb9\xeb\xb0\xaa\x5b\x82\x2c\xee\x55\xf6\x72\xeb\xfb\x93\x70\x5a\x5a\x70\xe2\x4f\x5f\x99\xf6\xfe\x07\x9b\xf8\xb9\xa2\x95\x44\xfd\xf8\xe4\xe0\xf3\x9a\xb6\xda\x1e\xd8\xa7\x4d\x72\x7f\x92\x46\x67\xd0\x26\xef\x88\xfb\xd2\x01\xa7\xd5\x8a\x85\x69\x07\xbc\x6a\xf9\x4a\x48\x1e\x9a\x3c\x88\x54\x6a\x36\xed\xf8\x48\xe3\x11\x0a\x83\xd2\x5e\xdc\x81\x8f\xe3\x3c\x3c\xf5\x67\xfa\x24\x84\xed\x4a\x96\xf9\xb2\x9d\x68\xe8\xf2\x2b\xbd\x28\x13\x12\x4c\xd6\xb4\x1f\x8d\xde\x9e\xb3\x4a\xb6\x86\x84\xaa\xe4\xc6\x00\x65\x1f\x72\x50\x85\xb0\x9c\x9f\xcc\x62\x41\x1b\xfb\x00\x7d\x95\xb6\xe6\x04\xfd\x74\xd6\x50\xf1\xc2\x38\xb2\x1c\xb8\x90\x4f\x3a\xda\xec\x1e\x89\xa7\x29\xad\x7e\x1a\x42\xa9\x9c\xe8\xa7\xc5\x15\x78\xd3\x3f\x5b\xbe\x78\xd4\x3d\x7b\xba\x7c\xe1\x58\xe3\x6a\x53\xae\x6e\x45\x97\xa8\xea\x65\xf3\x1b\x14\x2e\x5a\x78\xc6\x71\xcd\x5b\xe4\x51\x91\x6e\xa8\x14\x32\x39\x6d\x65\xaa\x46\x88\xe7\xd2\x68\xd1\x68\x30\xbc\xe3\x17\x66\xfb\x71\x87\x83\x11\x12\xd5\x46\x27\x32\x32\x52\xf3\xb1\x77\x38\x2b\xa0\xdb\x53\xce\x65\xca\x05\x9b\xf7\xa4\x8b\xf9\x6e\xab\x5d\xd5\x4f\x48\x87\xf9\x48\xae\x24\xa8\x7a\xbe\xe1\x12\x6d\x01\x1b\x18\x0b\x71\x63\x6a\x86\xce\x4d\x23\xa7\x43\x4e\xea\xcd\x0f\x29\x91\xd0\x40\xa7\x10\xcf\x89\x86\x49\xec\x38\xe7\x83\x97\x14\x84\xbc\xcb\x86\x5a\xd1\x5a\x16\x46\x4c\xaf\x2b\x1c\x12\xdc\xaf\x91\x7c\x00\x65\x98\x57\x39\x37\xfd\xc6\x61\xfc\x5b\x12\x8a\x6f\x5c\x35\xe6\xdc\x3c\xa0\x8a\x65\xb2\x7c\x76\xf1\x88\xb3\xd5\xa5\xa8\x57\xc0\x00\xc3\xf1\x42\x93\x72\xe0\x57\x8f\x34\x8c\x5b\xca\xc1\x82\x2c\x87\xbe\x6f\x58\xe6\xde\x32\xd5\x48\x1d\x1b\xf5\x19\x00\xa1\x46\xf8\xf6\xb0\x20\x21\x9e\x64\x6d\x4a\x93\x81\x33\x6f\x85\x53\x6d\x65\x34\x3b\x3d\xea\x1c\x58\x21\xea\x7a\x5e\xdf\x1b\x29\x13\x41\xf0\x28\xb8\xc3\x7e\x7e\x2c\xdf\xb4\xe5\xb7\x7e\x34\x6e\xcf\xa0\x86\x8d\x48\xaa\x07\xfb\xe9\x03\x4a\x41\x25\x6e\xd7\xd9\xc9\xa5\x46\x16\x4f\x1f\x6d\x8c\x5e\x94\xf3\xce\x20\x06\x4b\x62\x63\x01\x44\xd3\x2c\x50\x7b\x31\xea\xcb\xab\x3b\x53\x0c\xf6\xf1\x90\xfd\x01\xd4\x37\x4d\xd6\x6d\x44\xb5\xb4\xe1\xa5\xdb\xb2\x5e\x47\x66\x02\xd8\x60\x41\x74\xff\x95\x8f\x39\x12\xe0\xf3\xed\xe7\xe4\x1e\xf6\xa8\xbf\x12\x87\xaf\x61\xaf\x6b\x12\x2a\x10\x65\xe4\x02\x09\x02\x65\xcd\xe8\x73\xc2\x47\xe0\xbb\x91\x58\xc7\x47\x84\xe6\x05\xf2\x05\x8a\x7e\x89\xa4\x35\x5b\xc2\xe4\xfd\x8c\x08\xf8\xa1\xf4\x76\x49\xa4\xdc\x14\x49\x89\xbe\x36\x55\x87\xf4\xe9\xdb\x52\x1b\x7f\x4d\x6a\x73\xf7\x11\x6a\xaf\xe8\xb0\xac\xf0\xbe\xcf\xef\x59\xe8\x92\x6c\xfd\x81\x82\xeb\x32\xdf\xe9\x28\x39\x29\x4d\x9c\xd2\x71\xa6\x99\x9c\xa4\x53\x2e\xb0\x6a\x24\x10\x3f\x6c\x0a\x22\x8b\xe8\xb1\xef\xc4\xff\x52\x8d\x9e\x7f\x9b\x98\x62\xfe\x96\xe4\xdb\xfd\x26\xc7\xf9\x1f\x80\xc1\xea\x40\x40\x58\xf8\x14\x20\xa0\x85\x61\x57\xb6\xd5\x8a\x93\x5c\xe1\x9b\x27\xd9\xb7\x30\x38\xd1\x46\x21\x41\x30\x6e\xac\xa0\x4d\xf2\x4f\x35\xc8\x69\x16\x12\xc3\x76\xbb\xea\x1f\x36\x8b\xa8\x39\xce\x27\x9e\x43\x10\x10\xc9\x3c\x94\x03\xc2\xc1\xc8\xe2\x59\x9f\x32\x5f\xe8\x59\x04\x8c\x9a\xde\xe5\xbf\x7d\xa9\xe2\xae\x99\xa9\x27\xac\xc0\x57\xb2\x0d\xaf\x53\x8c\xd9\x01\xc1\xb3\x7d\xe3\x28\x34\x2d\x3d\x83\xd4\xb7\x74\xaa\xd5\x0e\xec\xa3\xfc\x4e\xf1\xfb\x47\x33\x81\xd3\x11\xa2\x02\x74\xea\x8c\xe1\x74\x38\x17\xcc\x37\x21\x08\x2f\xfc\x76\x0b\x85\x63\x47\xce\x2c\x46\x9a\xca\xef\x18\x07\x49\x94\xa2\x27\x10\x49\x2d\xbc\xdd\x3e\xe3\x33\x32\x63\xa1\xb3\x0e\x45\x4b\x77\x7a\xda\xf9\x02\x08\xb1\xfb\x66\xd3\x7a\xa3\x0d\x77\xb4\x3a\x89\x02\x33\xb5\x2f\xa7\x86\xbc\x23\xf5\x7b\xda\x32\x33\x0d\xb8\x9d\x74\xb4\xa2\x2c\x26\x2a\xd1\xcc\x8b\x09\x2f\x98\x56\x64\x30\x36\xad\x6e\x32\xda\xe9\x51\xcd\xf7\xc3\x92\xf8\xa1\x63\x00\x4c\xcf\x90\xa9\xeb\xde\xb7\x22\xb5\x49\x93\x2d\xd7\x6c\xa8\xb2\x61\x47\x63\x55\x02\xa4\xa3\x44\xc0\x42\xf2\xf3\xeb\xe3\x96\x3a\xa4\x8a\x50\x05\x70\x2b\x1c\x2b\x5f\x34\x67\x1a\x13\x25\xb9\x66\xa0\x82\xe9\x30\x54\x0e\xd8\xb1\xb6\xd1\x0d\xcc\xd8\x59\x33\x11\xd9\x26\x5e\x4b\x3e\xb6\xd1\x54\x89\x2e\x8e\x37\x4f\x94\xcc\xea\xda\x97\xda\x07\xd8\x1f\x6c\x3a\x54\xd6\xa7\x0d\x6b\xe3\x0e\xe8\x58\xb3\x4e\x9d\x2c\x7f\xab\x60\xf4\x7b\x55\xdd\x95\xaa\x50\x3a\x3d\x1a\x65\x8b\x64\x4b\xac\x84\x15\x17\x99\x95\x48\xc1\xcd\x1d\xeb\x7d\xdc\x1f\x97\x4a\x3d\x31\x02\xea\xa4\x78\x9d\x55\x35\x25\x55\xb0\x39\x94\xc5\x09\x09\x08\x5c\x83\xc6\x09\xa6\x93\x6f\x0f\xf9\x7d\x07\x0b\x8b\xf1\x2b\x36\x78\x4a\x75\x66\x46\x24\x3e\xac\x31\xaa\xd0\xba\x4d\xfb\xd5\x30\xa1\x04\xe9\x0f\xf9\x03\x94\x4b\xf0\x1a\xb5\xd9\x90\xce\xce\x87\x26\x0e\x68\x3d\xa9\x58\x31\x66\x35\x92\x35\x04\x29\x0e\x1a\x82\xc3\x44\xcf\x8d\x99\xba\x27\x2c\x5c\x51\x37\x2c\xea\x10\x37\x17\x5c\x93\xf4\x48\x98\xc5\x90\x02\x4b\x03\x6d\x8c\xf2\x89\x48\xd5\x15\xe1\x90\xb5\x34\xaf\x7c\xf3\xc9\x46\xab\x62\x66\x61\xc9\x87\xea\x9c\x74\x3d\x6d\x01\xc6\xb4\xb9\xea\xfe\x2a\xd2\x99\x2a\xdc\x5c\x8a\xad\x05\x34\x75\x9b\x6a\x9f\x36\x30\x35\x86\x28\xf4\x64\x1b\x08\xa8\x84\x8d\xa2\x84\xd4\xce\x36\xd7\x36\xaf\xbb\x9b\x12\xc6\xd7\x5d\x7a\xc3\x7e\xa4\x85\x76\xcd\xf2\xae\xb8\xec\x8e\xf4\x2c\x1a\x10\xba\x0e\xcf\x1a\xac\x5d\xb0\x50\x71\xd7\x04\x73\x87\x9e\x75\x0c\xc0\xaa\x6f\xa9\xb3\x31\x30\x99\x4d\x50\x00\x99\x33\x72\x71\xd8\x68\xee\xca\x10\x11\x37\xff\xec\xcc\x03\xac\xab\x7d\x59\x8c\xf2\xf1\x32\x49\xa7\xb0\x75\xc0\x43\xb5\xbc\x8f\x67\xcf\x55\x1d\x05\xb0\xbf\xe4\xae\xd4\x5e\x78\x63\xf0\x5e\x19\x35\x08\x1b\x87\xd7\x34\x92\x3e\x87\xc2\xb8\xa4\x21\xae\x36\xd1\xee\xbc\x46\x49\x2a\x25\x93\x0d\x9a\x7c\xe2\xae\x3f\x27\xc4\x34\xeb\x75\xc9\x86\x32\x6a\x89\x0f\x4c\xfc\x56\xf9\x5e\x32\x69\xc0\xeb\x56\xd2\x6c\x5e\xb7\x2a\x2b\xda\x90\xcd\xee\xc1\x9a\x55\x6d\xe6\x9e\x2e\xf9\x7b\x43\x12\x08\xec\xc4\x7f\xa2\x14\xcb\xce\x75\x12\x79\x86\x46\x56\x0a\x28\x17\x55\x7f\xef\x4f\x8c\x53\xcd\x21\x25\x19\xdc\x01\x76\x8f\x97\x96\xa6\xf5\xc8\x99\xe9\xf1\xd6\x96\x94\xc2\x89\x11\xea\xa5\xa5\x13\xd6\xb1\x77\x0b\x1c\x0e\x2c\x8a\xc3\xb4\x1d\x1c\x09\x8f\x1f\x75\x8f\x79\xc1\xac\x6c\x11\xc0\xef\xf3\x9e\xd8\x62\x2d\x0a\x8e\x70\xa8\xb0\xaa\x16\xbb\x26\xc0\x55\x04\x6c\x01\x7f\xb0\xa0\xe2\x73\x42\x9a\x28\x1c\x88\x34\x35\x49\xcd\x3a\x3f\x95\xc5\x74\x2a\x31\xff\x1b\x25\xd5\x9e\x92\xba\x28\x08\x55\x74\xe1\x04\x34\x97\x51\x17\x7b\x90\xba\x44\x0d\x48\xb1\xf5\x48\xc9\xfb\x79\x7a\x2e\x09\x53\x99\x87\x0a\x73\xaa\x8a\x24\xd9\x03\xef\x59\x30\x5a\x59\x08\x37\x68\xf9\x1f\x58\xb0\xdb\xb1\x5c\x40\x58\x90\x56\x40\xb8\xe6\x50\x80\x24\xc0\x1e\xd8\x40\xdd\x63\xd3\x2c\xf4\xc0\x3a\x70\x96\x90\xb6\xcc\xf5\x18\xec\x50\x2e\x53\x36\x96\x12\xe1\x90\x56\xa5\x13\xdd\xe5\xa4\x90\xdd\x55\xb9\xb3\xeb\xd0\x6a\xb1\xdb\x5e\x4f\xd1\x97\xec\xb2\x87\x1f\x74\x1a\xc0\xc1\xde\x0c\x75\x5c\xbc\xd5\x64\x32\xec\x0b\xb6\x88\xf9\x09\x7f\x44\x86\x9b\x70\x5c\x1e\xd8\x2a\x31\x75\xab\xe6\xa5\x18\x80\x17\xa9\xc2\xf1\xc8\xee\x17\xb6\x7d\x66\x22\x3f\x74\x0b\x15\x63\x90\xd0\x45\x20\x45\xaa\xf2\x1a\xc0\x42\x78\x0f\xd0\x2b\x5e\x41\x20\x84\xce\xca\x74\xd3\x1c\xd2\x6d\x55\xdf\x76\x8a\x5f\x67\x4d\x31\x2d\x3b\x3d\x47\x06\x01\x8b\x9d\x87\xc5\xaa\xaa\x1e\xca\x9f\x12\x4b\x89\x19\x1f\xc9\x69\x94\x43\x29\xa7\xe2\x98\x19\xa8\xf7\xe5\x0c\xd9\xe9\x29\xb2\x67\x61\xbd\x96\xac\x55\xe0\x0f\x66\xf6\xab\x6e\xa1\x9b\x92\xc5\x73\xb0\xc3\x57\xca\x85\x08\x3f\x4d\xd3\xa9\xe5\xd2\xb3\x1f\xce\x83\x99\x43\xa1\x74\xb5\x1c\x84\x2e\xa6\x0c\xc6\xbc\x1c\x04\xc5\xca\x25\x09\x4b\x3a\x1e\xec\xed\xac\xda\x49\xa4\xce\x47\x2d\x15\x87\xbf\xd3\x4a\x50\xbc\x20\x3d\x7b\x34\x99\xd0\xdf\xf0\x8e\x70\x29\xd3\x37\x3e\x6a\x85\x27\x26\x2e\x08\x42\x70\xd8\x47\x83\x1d\x53\x96\x36\x60\xa6\xf3\x2f\x10\x98\x91\x4f\xe8\x86\x11\xde\xec\x58\x4b\xb3\x8d\x84\xc2\x33\x75\x02\xb8\x72\xc6\x6c\x50\xfe\x0e\x0e\xb3\xb1\xad\x22\xd2\xb3\xb4\x85\xa3\xd2\xf4\x68\x4c\x93\xbd\x63\xf5\x0e\x34\xb7\x70\x3a\x46\xf0\x0b\xa1\xfe\x1c\x76\x65\xf1\xa9\x0d\x9d\xc8\x93\xdc\x15\x1c\x72\xd2\x04\x21\x00\xea\x4a\xe7\xb5\x94\x53\xe1\x46\x6c\x4e\x97\xf8\x22\x07\xa0\x21\x46\xb1\x36\x5a\x9a\x07\x3c\x64\x6c\xfb\x96\x16\x9d\x0e\xde\x91\x1d\x6b\xc2\xd2\x22\xf6\x05\xee\xd5\xc0\x9d\xeb\xb9\x16\xe9\x9f\xda\x16\xf3\x7f\xa4\x2c\xc7\xdb\x3e\x4b\xb6\x8d\x59\xa7\xca\xac\x5d\xa9\xb0\xec\x84\xc6\x80\x3d\x50\x3a\xe3\x46\x01\x4c\xc4\x43\x04\x58\x08\x62\x76\x54\xcb\xce\x22\x2b\x31\xec\xbd\xff\xdf\x2c\xc3\x51\x87\xce\x32\xec\x87\x3a\x22\x1b\x1e\xe3\xe8\xc4\x99\x10\x10\x15\xe0\xfc\xd5\xa5\x0f\x4e\x55\x5d\x7c\x77\xb8\x72\x37\x22\xd3\x33\x9a\x28\x0b\x47\xb0\x12\x01\x38\x2c\x0b\x78\x08\xd9\x40\xd8\x8f\x08\xf8\xdd\xc4\x88\x19\xf3\xd7\x53\x68\x30\x84\x15\x81\x65\x79\x80\x0f\x34\x91\xfe\x54\x23\xda\x31\x22\xc4\x69\xeb\xa2\x58\xee\xc5\x5f\xe9\x45\xa2\x13\x55\x1b\x36\xd5\x7a\x43\xf3\xaa\x76\xec\xb0\x04\xd7\x36\xaf\x98\xd7\xea\xf8\x17\x6d\xbc\x66\x5d\xb3\x05\x88\x7b\x10\x65\xdc\x71\xdb\x67\x5d\xdf\x36\xf5\xfa\xc5\x79\xc3\xea\x16\xdb\x51\xf8\xa8\xf8\xe9\xd9\x53\xcd\x27\x96\xc1\x6b\xc8\xd1\x92\xaf\xaa\xfe\xf5\xb0\x7c\xdc\xa5\x6b\x92\x0d\x70\x80\x3c\xcb\xd3\x4d\x5b\xde\x3c\xff\xfa\x51\xf7\xf5\x0b\xf5\x52\x4b\x4c\xd1\xa1\x76\x68\x79\xf6\x34\x7f\xc1\xd2\x73\xd7\x6c\x49\xa8\x8d\xab\x34\xbb\x9d\xac\x2f\xb1\xbf\x9d\x40\x62\xfc\x70\x6c\x97\x35\x30\x57\xb6\x8a\x1f\x6a\x70\xe1\x68\xdd\xaf\x8f\x2e\x5b\xc2\xf6\x05\x3d\x48\xe9\xa7\x1c\xf7\x9c\x67\x46\x05\x39\xbd\x28\x65\xeb\x1b\x10\x11\x33\x36\x6d\x27\x30\x61\x30\xc1\x7c\x65\x7b\x4e\x3a\x0c\x76\x1c\x44\x86\x53\x86\x61\x11\x16\x8a\xae\x5a\x36\xde\xaa\x5a\x8b\x02\x3a\x1b\x02\x11\xf6\x5d\xa3\x4e\x84\xd4\x32\x3d\x41\x9a\x48\xa7\xe4\x78\xea\xa9\x69\x2c\xe4\xa9\x37\xed\x28\x45\x06\x84\xa8\xad\xba\x30\x09\x51\xc0\x4b\x88\x52\xcb\xaa\x2e\x84\xf0\x94\x6e\x34\xee\xc0\x11\x0c\x1d\x47\x35\x03\xc1\xc6\xc6\x09\xfd\x1d\x60\xee\x2a\x6a\x3f\x38\x92\x68\xbf\x0f\x75\xb0\xdf\x84\xa0\xb3\xbe\x11\x5b\x93\x4e\xf2\x3d\x49\xec\x88\x39\x3a\x95\x06\xaf\xb9\xb8\xd3\xb8\x37\x75\x4a\x5a\x95\x57\x9a\x89\xd5\x02\x60\x82\xa2\xce\x21\x02\xbf\xbc\xf2\x66\xad\xa8\xbf\x58\xa3\x89\xb0\x30\x44\xbc\xb6\xc3\x36\xe2\x3f\x4e\x4f\xdf\xbf\x59\x24\xae\x3f\x6b\xf3\x97\x9c\xa4\x0e\x19\xc1\xc1\xe9\x8d\xcc\x50\xc6\x3b\xd4\x79\x2b\xa4\xba\x99\xa9\x50\x13\xb4\xe8\xe6\x34\x99\x8f\xcc\x25\x2e\x17\x14\x97\x5d\xa0\x4b\x4b\x6f\x18\xc9\x98\xb7\xb9\x99\x7e\x45\x88\x75\x16\x1d\xe6\xa9\xfb\x7b\xe6\x16\x41\xa4\x48\x2e\x08\x3a\x60\xbf\x8f\x42\x54\x08\x12\xfa\x64\xca\x12\x62\xeb\x48\xdf\x06\xac\xc4\x1f\xe6\x06\x94\x00\x32\xdc\xdb\x7a\x46\xe3\xf5\x47\x45\x38\x68\x51\x73\x63\xa9\xe5\xab\x54\x18\x91\xf8\x3f\x79\x5c\x22\xdb\x28\x8e\x43\xe5\x86\xda\x3c\x94\x5b\x8e\x64\xd3\x01\x79\x27\xa0\xaa\x32\x91\x0b\x50\x81\x9c\xf3\x8f\x23\x07\xdd\x59\x2c\x6b\x1b\xda\x17\xac\x31\x82\x20\x02\x86\xd7\x4f\x74\x10\x63\x98\x67\xa7\xef\xde\x5d\x5e\x7b\x3e\xc9\x94\x55\x17\xc4\xcd\xbf\x72\xf1\x2f\x93\x71\x59\x14\x0c\xc6\x87\x80\xa8\x08\xc2\xc7\xe1\x68\x8d\x63\x70\xe1\xc6\xb7\xd6\x29\xb9\x6e\xb0\x9b\x1b\x1e\x8b\xd4\x28\xe2\xf1\x17\xc7\x44\xfc\xe4\x13\x1f\x30\x9f\x13\xb3\xd2\x5d\xf2\xff\x24\x34\x74\x06\xa6\x69\x50\xb3\xb7\x60\xfb\x70\x4f\x1a\x40\x53\x4c\x0c\x9f\x34\xb0\xa1\x1b\x72\xc8\x70\x84\xfb\x06\x7c\xf1\x26\x85\x77\xeb\x84\xed\x38\x4d\x0b\x1a\x64\xe4\x0e\x75\xf5\xeb\x80\x13\x92\x25\x38\x3a\xf1\x39\xac\x6a\x59\x6d\x85\x79\xfe\xd9\xfd\x90\x7c\x4e\x8d\x62\x21\x83\xce\xe9\xd7\xb3\x6e\xcf\x91\x62\xc4\x9b\xbb\xe7\x5f\x93\xc8\x4d\x1a\x0b\xfe\x3e\x61\xfb\x80\xa6\xf2\xa2\x1a\xe8\x28\x22\x01\x8c\xdd\xc6\xb4\x9e\x54\xe5\x05\xeb\xfa\xb7\x66\x42\x1a\x87\xad\xa3\xcc\x22\x1b\xb9\x0c\xe1\x8d\xc8\x9d\x19\x96\x8a\xab\x62\x03\xe8\xc5\x78\x94\x06\xd3\x62\x76\xcd\xe4\x7e\x5b\x86\xa8\x53\x17\x81\x2e\xf4\x39\xfd\x6b\x2b\x84\x67\x4a\x3e\xdf\x21\x48\x83\xfb\x03\x2e\xd3\xf7\x7b\x45\x04\xb0\x62\x1d\x65\xb1\xae\x7a\x12\x93\xf9\xae\x05\x94\x57\xda\x41\xc4\x25\x71\xfd\x40\x52\x96\x33\x53\xd7\x60\x51\xb1\xaa\xab\x3e\x63\xab\xfe\x4e\x42\xca\xa9\xd9\x7c\x2b\x62\x45\x8c\x79\xf1\xe0\xa6\x1f\x7e\x39\x3d\xbf\xf8\x65\xb1\x2b\x2c\xc2\x44\xf1\xa9\xa1\x25\x01\x46\x8b\xf2\x26\x1f\xb6\x66\xbd\xc2\x84\x91\x91\xfe\x8c\x0c\xbd\x8d\x40\x8a\x06\xe1\xef\x4e\xce\x48\xb9\x9f\xf0\xc6\x72\xbe\x61\x31\xf2\xdb\x23\x36\x9d\xb1\x5b\xe5\x8f\x9b\x76\xc6\x2d\x3c\x6c\xe1\x61\x9f\x7b\xc6\xf6\xba\x54\xe3\x32\x22\x6f\x64\xa2\xb7\x25\x2c\x2a\xde\x5d\x97\x90\xb0\xf8\xb0\xf4\x38\x71\x9b\xba\x91\x1f\xa7\xf1\xe5\x76\x28\x47\x44\x2e\x78\x34\x1a\xb7\x9e\x74\x59\x2e\xf4\x12\x47\xb0\x2e\x0a\xb1\x40\x38\x71\x66\x92\x35\x3b\xb2\x59\x6a\x55\x6d\xca\x41\x99\x6d\x1d\xf1\xa1\x16\xa3\xf6\x46\x32\x25\x68\x14\x11\x6a\x10\x5f\x63\x33\xa4\xf9\xcf\xf3\x30\x00\x3c\x91\x4d\x61\x3b\x4d\xb7\xc8\x8d\xdb\x6b\x08\x25\xe6\x38\xd1\x78\x93\xe1\xbe\x49\x80\xa9\x30\xba\x83\xd9\x5b\xc1\xfc\x79\x7f\x9f\xb1\x31\x04\x2c\x79\x7f\x9f\x20\x06\x82\x0e\xb4\x0c\xe7\xa5\x64\x82\x41\x6e\xab\xbd\xdc\x56\xa2\x82\xaa\x94\x40\x46\x24\x2e\xff\x2d\x11\xa4\xb8\x15\xc2\x42\xe3\x0a\x13\x17\x10\x23\xfe\x09\xfc\xaa\x67\x89\x57\x8c\xb3\xcf\xbf\xce\x96\xb4\x47\x6f\xbf\x0e\x24\x60\xbe\xec\xc4\x62\xef\x57\x24\x59\x1d\xd4\x01\xf9\x51\x52\x89\xfd\xfe\x0b\x7e\x0d\x1c\x18\x27\xde\x4e\x4e\x24\xfa\x8b\x6d\x9c\x89\xde\xb1\x61\x66\x94\xb0\xc0\xa9\x6c\x83\x84\xcd\x90\x73\xfc\x3a\xf0\x2c\x45\x78\x7f\x9e\xfe\x3b\xff\x4a\x5f\xf1\x2f\x9d\x0a\x6f\x63\xb7\x47\xb1\xc2\xa3\x8d\x1d\x46\x8a\x81\xe3\x68\xb8\xa5\xdf\xd3\x12\x5e\x12\x60\x5f\xe3\x4a\x0c\x90\x63\x92\x93\xfd\xc0\x3e\x74\x5e\x77\xeb\xed\x3d\xe5\x20\xc0\x9b\x33\xf9\x0c\x0b\x5a\x70\x06\xf0\xa8\x8d\xc4\xb1\x0a\x65\x11\x7d\x5b\x42\xde\xa2\x7f\x5a\x96\x11\x70\xd6\xe7\x30\x79\x0a\x10\x91\xdc\x7f\x4e\xaf\x29\x47\x21\xca\xb0\x28\x51\x50\x94\x8f\x6f\xf5\x60\x1b\x75\xe0\xb8\x9c\x20\x92\xdf\x96\x5d\x4f\x28\x82\xfa\xe8\x7e\x24\x3c\xc6\xaa\x97\x50\x3e\xa4\x12\x0d\x34\x15\xb3\xb6\x24\x13\x18\x0d\xdb\x9c\xc3\xb6\x3e\xe4\x07\xf9\x49\x98\xd6\x6b\x40\xaf\x25\x25\xd9\x08\x44\x16\x50\x84\x2b\x3b\x78\x9c\xeb\x4a\xc3\xef\x2d\x9d\xd8\x00\x16\xd3\x81\x58\xc9\xe8\x16\x52\xba\x1a\x95\xdf\x88\xbc\xff\x92\xa5\x7d\xcb\xcb\xc1\xbf\x52\x0b\xab\x70\xf9\x3b\xda\xfe\x62\x1f\xbb\x90\x94\x2b\x29\x24\xe2\xe7\x9c\x2f\xbc\x59\x9e\xc5\x54\x5e\xf2\x7f\x97\x4b\x04\xa3\xfb\x87\xfe\x27\x8a\x79\xce\x55\xb5\x4c\xae\x3d\xf9\xec\x4c\x78\x9c\x14\x62\x39\x26\x85\xd9\x7e\x9b\xaf\x4a\x17\xc3\x09\x20\xf0\x6d\xbe\x72\xa5\xc0\x24\xfa\xb1\xe3\x7b\x49\xe5\x8f\x68\x3b\xd3\x2f\x2b\xa1\xcd\x40\x67\xa1\x2b\x3a\xe3\x9f\x85\x15\x12\xee\x39\x2a\xd0\xc6\x10\xf5\x1f\x96\xd1\xf9\xc1\xbc\x49\x8c\x62\xef\x58\xba\xe6\xb4\x49\x1d\xa3\x1a\x8e\x9a\x42\x62\x3a\x06\x73\xb4\xe5\xdd\x91\x9a\x74\x30\x70\xec\x3a\xe4\x4a\x4d\x8e\x20\xf4\x20\xc2\xf1\x33\x2d\x59\x70\x38\xae\xdb\x10\xa7\x70\x63\x61\x53\xcc\x81\x4a\x07\x1c\xbf\xc4\x81\x79\xbe\xcb\x42\xf5\xa4\xb9\x4a\xc2\x55\x8a\x6c\x79\xaf\x75\x84\x99\x14\xec\x24\x3b\x52\x65\xc7\x9e\x30\x70\x59\xad\x72\xe1\x32\xc2\x2a\xbc\xc8\x68\x98\x20\x24\x9d\x3e\xfa\xf4\xdd\xe7\x8e\x5b\x76\x86\x88\xa7\x8f\x3e\x7d\xff\x99\x58\x31\xfe\x31\x2f\xb6\xda\xfb\xb6\xbc\xab\x9a\x01\x77\xfe\x34\xe9\x49\x0d\x91\xbf\xef\x38\xca\x57\xb3\x64\xd9\x4d\x82\xf7\x34\x17\x97\xaf\x9a\x6d\xe3\x69\x12\xbf\xc6\x00\xa2\x2a\x3c\x52\x52\xe9\xe2\x62\x90\xad\x5b\x8c\x47\x70\x82\xd4\xa3\x05\x11\xc8\xb2\xa8\xb8\x9d\x5f\xe8\x5f\x5c\x30\x72\xf8\xc4\x85\x2e\x52\x4c\x06\x88\x78\x31\xbb\xb0\x32\x6d\x45\xdd\x26\x00\x75\xba\xca\x2c\x98\x97\x64\xd1\xb9\xec\x1f\x08\x31\xea\xec\x64\x66\x55\xd5\x72\x61\x87\x9b\x65\x13\x18\x4a\xc5\x19\xa4\x8d\x1e\x77\x52\xcc\xf7\xea\xb5\x53\x19\xa4\x0f\xd2\x55\xf5\x28\xd2\x3d\x93\x80\xaf\x07\x1c\xc8\x6f\xc9\xa0\x78\x86\x7f\x04\xa5\xf3\x3c\x64\x0c\x50\xc8\x41\xcb\x89\x47\x5d\xd4\x37\x1d\xe1\x43\x99\x29\x13\xa5\x4d\x4e\xbf\x52\xfc\x1a\x0f\x81\xd9\xe9\x5c\xdf\xd6\xf2\x68\x46\x84\x90\xe5\x86\x44\x21\x09\x47\x94\x33\x3b\x38\xcb\x08\xa3\xea\x2a\x57\x2d\x58\xb1\x1a\x35\x2f\xb5\x5c\xf5\x59\xec\xd8\x36\x40\xa4\x5f\x58\x30\xa3\xd0\x84\xa5\x7e\xd2\xe7\x34\x63\x3e\x3d\xd2\x6f\xec\x9e\xda\xb7\xf1\x24\x4b\xf1\xf6\xf0\xff\xb0\xc0\x5d\xb0\xd0\xa6\x32\x21\x29\x6d\x11\x8d\x6b\x8e\xbf\x78\x70\xe2\xe2\xe4\x1e\xdf\x53\x73\x4f\x76\xbb\x27\x45\xf1\x78\x66\xd6\x01\x3d\xb9\x69\x8b\x0e\xe0\x08\x4b\x99\xd9\x88\xb0\x82\x96\x82\x7d\x39\x8f\x3b\x06\x88\xd6\xe9\x23\xc7\x0b\x94\xac\x70\xa4\x85\xc7\x1b\x9c\x0c\xc1\xda\x75\x0d\xe9\xfa\xcd\x9e\xd0\xee\x4c\x3b\x6c\x87\x90\x08\xaa\x70\x26\x23\xcf\x5d\x50\x34\x0a\x13\x7d\x70\x78\x86\x07\xf1\x28\x75\xac\xc6\xee\x8e\xa0\x44\xae\x78\x1e\x45\x48\xc0\x49\x3c\x52\x1d\x37\x99\x01\x1c\xf1\x12\xdf\xed\xbf\x92\x9f\xcc\xf5\x3b\xb7\xfa\x5f\xe2\x28\x73\x17\xcd\x2d\x6f\x21\xa4\x0d\x9f\xbc\xa4\x7c\x51\x70\x41\x04\xa8\x39\x0b\x7f\x7b\xb0\x4d\xd3\xdc\xca\x25\x99\x25\x92\xbe\x84\xb4\x7e\x2b\xe4\x3b\xb8\xaf\xe3\xd2\xa2\xdc\x6f\x9b\x7b\x73\x80\x9c\xe3\x97\x46\x16\x18\xc8\x32\xef\xaa\x55\x78\x89\xfe\x67\xce\x98\x99\x45\xc1\x14\xd0\x66\xff\x10\x01\xe6\x1c\xbf\xd2\xff\xc9\x64\xe3\x40\xd4\xe7\x7e\x69\xf7\xa6\xae\xd8\xf3\xee\x4a\xd5\xe7\x19\x74\xa5\x2e\xda\x69\x5f\xea\x3e\x64\xfd\x60\xde\x30\xe5\x7c\xe7\xc7\xaa\x18\xf5\x8c\x55\x7a\xb6\xa9\x3a\x1f\xe3\xc4\x8d\x3e\xe7\x3e\x8f\xa3\xfc\x1e\xa0\x25\x37\x14\x17\x40\xc4\x8a\x8a\x26\x2f\x2d\x06\x69\x0a\xe6\xec\x7c\x3e\xee\x28\xb6\x02\xb0\x15\xbb\x16\xb7\x22\x62\x8f\x38\x46\x89\xb3\xe2\x80\x27\x22\x7d\xb9\x74\xec\x2f\x1c\x20\xfa\x19\x46\x61\xbe\x6f\x61\xfd\xe2\x3d\x06\x44\x1f\x72\x20\x57\x27\x56\x14\x8d\xa2\x12\x8f\xba\xd8\x07\x73\x77\x5f\x87\x9d\x0e\x63\xc3\x0f\xd7\x13\x69\xdb\x5d\xba\x11\x97\xbc\x0d\x15\x65\x21\x29\xc6\x01\x28\xc0\x7d\x60\x84\x18\x01\x1a\x52\x2e\x89\x7b\x89\xd3\x42\xaa\xe5\x51\x00\x97\xc4\x0a\xc2\x32\xa3\x66\xd1\x65\xbe\xba\x75\x23\x62\xe6\x58\xb6\x3d\x42\xa7\xa6\x68\x67\xd7\xed\x0a\x02\xd6\xb3\xfd\x8b\x27\x30\x2e\xc8\x1d\x6d\xcc\x42\x78\x40\x75\x13\x20\x04\xce\x17\x76\xa6\xdc\x55\xc5\x40\xe4\xcd\x8b\xb1\x78\xf6\x74\xff\x22\xae\x4f\x14\x01\x83\xd3\xd1\x36\x46\x0b\xc7\xda\x6e\x85\x0b\x1f\x1c\x9b\x88\x20\xb9\x1b\x1f\xfb\xd9\xa1\x87\xa3\xbb\x28\xe0\x56\x01\xa9\x1b\xc7\xf9\x42\xe8\xc0\x14\x27\x66\x19\xc6\x4b\x1d\xb0\x0e\x3b\x18\xf6\x36\x66\x01\x69\xc3\x03\x61\x34\x3b\xd3\x94\x78\x36\x46\x66\x35\x1f\x8a\xe7\x86\x66\x15\xda\xe3\xc3\x8b\x2d\xed\xe9\x8c\x85\xdd\x81\xb2\xcb\xce\x33\x55\xd1\x66\x8b\x02\xf3\x39\x0b\xb2\x8f\x57\x18\xb9\x0b\xa3\xb6\x62\x9f\x61\x30\x40\x39\x8d\x8e\xb5\x73\x36\xdb\x86\xfa\x45\x82\x56\x10\x71\x5b\x21\xb6\x32\xd3\x4b\x64\x12\x2d\x94\x8e\x83\x1b\xb5\xf4\xb0\x69\x82\x2b\x0c\x18\x54\x8a\xcd\x1a\x0e\x64\x11\xcf\xf5\x20\x47\x88\xe2\x45\x0f\x94\xd1\x49\x63\x9b\xcf\x8e\x1b\x84\xc3\xef\x06\xe2\x2d\xdb\x8a\x16\x1d\x47\x86\x3e\x85\x70\x79\x75\x8d\x4b\xe6\xc4\x0b\x89\xd1\xac\x99\x5e\xd3\xbf\x6c\x48\x07\xe3\x90\x53\x7e\x91\x80\x23\x01\xd6\x69\xb3\x5a\xb1\xff\xbf\xaa\xf5\x12\xe7\xa1\x34\x3f\x5b\x5d\x6c\x25\x16\x20\x8c\xa4\x30\xbe\x2b\x16\xb5\x14\xaf\x0e\x30\x13\xe8\xf6\xe5\x8a\x44\x96\x45\xfa\x96\x04\x38\xbe\xca\x2e\x8f\x1d\x80\x61\x3e\x68\x80\x73\x33\x81\x25\x8c\xd5\xbf\xc5\xf4\x0c\x75\x6f\xa2\xd8\x41\x8a\x79\xef\x39\xde\x50\xd4\x54\x2e\x20\x89\xa3\xdc\xde\x48\xec\x28\xbb\x1a\x21\xe8\xc9\x05\x7a\x76\x77\xc8\xbd\x62\xb6\x11\xa2\x01\x8d\x82\x80\xc7\x16\xd7\xad\x78\x66\xfb\xb2\x65\x89\xc5\xe2\x85\xc2\x50\x91\xf1\x98\xa0\xdf\xd9\xb8\xde\x08\x5b\xc0\xf2\x41\xac\x95\xbb\x71\x27\xcc\x8b\x59\x22\x34\x17\xb8\x59\x8d\xf7\x72\x1f\x8e\x4f\x3a\xc2\x17\xc2\xb1\x0d\x44\xce\x0f\x5c\x7a\xe1\xb8\xe4\x41\x97\xc3\xa2\xb0\x80\x50\xee\x67\x66\x44\x7a\x20\x33\x82\xc4\x47\x34\x81\xf0\xae\x78\x00\x99\x3f\x7e\xcc\xc2\x14\xdc\xcb\x01\xaf\x23\x4a\xd4\x3d\x85\x16\xc3\x6b\xc2\x42\xbe\x0f\x6c\xa3\x80\xca\xa3\x57\x6e\x30\x43\xbd\x1e\xf7\x8c\xef\x76\xbd\x60\xea\x7d\xf6\x14\x49\xbb\x12\x68\x94\xc7\x8f\x6a\x04\x14\xc7\x0f\x26\x34\x84\x3f\x1c\x7d\x6d\xb9\xce\xdb\xc2\xa2\xdb\x95\xfa\xd9\xf5\x0c\x2a\x0f\x83\x97\xf2\x2d\xc9\xeb\xda\x04\xed\x56\x02\xb9\x65\xbb\x1b\x11\x0a\x3f\x09\x63\x2a\x0a\x73\xfe\x42\xb6\x16\xc7\x85\x10\xc1\x0f\x7b\xde\x03\xb2\xa1\xac\x1f\x4c\xfb\x9b\x3f\x5d\x5d\xbe\x3b\x49\x7f\x7b\x72\x38\x1c\x9e\x70\xf5\x27\x43\xbb\xe5\x08\x8a\x82\xa3\xe7\xff\xc7\xc5\xdb\x93\xb4\xec\x57\xdf\x2e\x48\xb6\xc7\xd6\xf0\x92\xb1\xba\xc5\x6f\xd8\x5d\xcf\x64\xc9\x7a\xdf\x3f\xbf\x65\xf6\x72\x49\x4b\x1f\x30\x09\xaf\x6c\x85\x4c\x9b\x97\xdd\xcc\x4e\x4a\x05\x62\x7e\xf2\x12\x63\x49\x9a\x14\x2e\x69\x22\xe1\x0b\x80\x55\x5b\xbe\x8f\x8c\x0e\x11\x6e\x90\xdf\xb1\x5b\x71\xd8\x16\x42\xa7\xc6\xd1\x68\x76\x8a\xb2\xb2\xf8\x69\xdc\x12\xac\xd1\x78\xaf\xe1\x79\xfa\x27\x56\x03\x19\xa5\x42\x05\x5c\x64\x54\x00\xe0\x90\x96\xb0\xc3\x52\xbd\x70\x5a\x8e\x0b\xbc\x5f\xe0\xbc\xec\x11\x63\x36\x47\x1b\x32\x72\x37\x36\xbf\x9a\xb6\x51\xe9\x5c\xa3\xc6\x5a\xe1\xde\xe2\xed\x8e\xa8\x79\xb4\x07\xf8\x5c\x3a\x8c\xf7\xc1\xf8\x48\xd2\x4d\xe6\xd9\xbd\x6e\xb2\x09\xc7\x57\xc0\x2f\xed\x33\x95\x20\x26\x12\x5d\xd0\x83\x4a\x76\x93\x1e\x24\x14\x26\xd3\x59\x5a\xf0\x37\xc2\x63\xce\x5d\x5e\x7c\x04\x19\xd5\x80\x81\xc4\x24\xc3\x08\xe9\xb6\x24\xe6\x65\xe1\x0e\xe7\xc3\x2c\x0a\x3a\xba\x62\x10\x84\x1a\xb1\x3f\xd1\x7c\x6f\x93\x40\xab\x50\xcc\x90\x56\x2d\x0c\x42\xc2\x35\x46\x85\xe3\x87\x84\x46\xc5\xac\x59\xc8\x4b\x65\x67\x92\x4a\x12\x52\xb1\x6f\x16\xcb\xb6\x39\x74\x1c\xfb\x83\xe7\x56\xd8\x1b\xc1\xbf\xd3\x2b\xfc\x16\x90\x7d\xde\x0a\xcf\x94\x84\x64\x8a\xf5\x9c\x32\x25\x21\x99\xcc\x3a\x26\xcf\x5d\x9c\x53\x09\x5e\x98\xe0\xd7\x67\x38\xe8\x55\x4a\x16\x52\x85\xb6\xcb\x21\xe3\x54\xd6\xf5\x39\xfc\x05\x57\xac\xea\xa0\xd2\x15\xe7\x28\x18\x27\x0d\xa3\x16\x01\xc1\x96\x2d\x0b\x43\xc6\x39\xe7\x83\x21\xc0\x0d\x0d\x8e\xc0\x68\x69\x2a\x1c\x64\x1e\x24\x8c\xa5\x20\x08\x53\xb2\x3d\x84\x22\x08\x48\xfd\xf9\xcd\x3b\xf9\x09\x7f\x88\x06\x65\xc3\x21\xf2\x92\x3d\xd3\xe6\x65\x59\xcc\x79\x5b\xac\x4c\xbc\x56\x22\xff\xdb\x2b\x76\xf8\xe5\x20\x8a\x36\xbf\x81\xa5\x88\xff\xbb\x5c\x3a\x2c\x7d\xb5\xf7\x6d\xf9\x64\x5c\x8d\x90\x23\xa8\xbe\x42\xc2\xe5\xab\xa5\x87\xff\xb9\xbc\x9c\xad\x3a\x01\x0e\x1f\x15\x1e\x23\xe6\xb3\x21\x52\x7c\x44\x8c\xac\x62\x05\x47\x35\xbe\x51\x87\xa0\x0e\x7f\x4b\x19\xb4\x83\x17\xe1\x0c\xa2\xcf\xd7\x2e\x02\x29\x5f\x8b\x1d\xda\x97\x41\x74\xb2\x8b\x21\x51\x1d\x7f\x55\xd9\x54\x36\xef\x93\xa3\x72\xbc\xb9\xb4\x0a\x5d\x7d\x94\xc9\x3e\x3e\xc4\xf6\x77\x9b\xc5\x78\x21\x9c\x3d\x5c\x71\x96\xe2\xb7\x83\xb2\x93\x80\xc9\x25\xdb\x15\xc1\x61\x20\x04\x14\x6e\xdb\x8b\xbc\xbd\xe5\x47\x58\x60\xa1\xb7\x06\x0e\xad\x06\xf3\xf3\xff\x70\xc5\xf4\xf1\x9f\xf7\x92\x9a\x74\x18\x3b\x88\x50\x1b\x32\xa9\x89\x41\xae\x02\x9f\x5e\x72\x71\xe4\xad\xa4\xe4\xd5\xbe\x31\x65\x4c\x43\xf1\xa8\xec\xc9\x78\xdd\x02\x78\x87\xe8\xbf\x94\xff\xe7\x7f\xfd\x6f\x62\xf6\x7b\x52\x52\x7b\x84\x59\xea\x0d\x3f\xbf\xee\x16\x60\xe0\x9f\x6a\x7a\x02\xfd\x3b\x18\x88\xa0\x3f\xd5\x9b\x19\x94\x9a\xd0\x28\xbf\xe3\x62\xf4\x7d\xc5\x36\x80\x98\xc8\x21\x4d\x7a\x32\x87\x75\x72\xdc\x86\x11\x55\xa6\xfa\xbf\xbb\x61\x64\x8b\x8b\x45\x93\xb8\x7d\x25\x3a\x31\x11\xa8\xb9\x00\xe0\x72\x05\x86\x74\x96\xcf\xfe\x16\xab\x5b\x88\xe8\x06\x2b\x44\x48\x0f\x63\x08\x7b\xc5\xe4\x37\x7d\xb4\x4e\x44\x72\xb9\x32\xcf\xac\xc5\xc5\x15\xc9\xbd\x30\x89\x1a\x76\x8d\x84\x1d\x3d\xee\x2c\x74\x58\x5f\x53\x40\x70\xee\x4c\xfc\x76\x18\x93\x4c\x12\xb9\x9a\x84\xe5\xbe\x9b\x1a\xc3\xa3\x37\x2c\xe1\x22\x37\xfd\xda\x8e\xd9\x22\x51\x2b\x2d\xbb\x6d\x39\xc1\x57\x12\xf9\x65\x40\x26\x3f\xb1\xa0\xbd\x41\x06\xed\x6b\x64\xe0\xb2\x2e\x1c\xd3\xfc\x3f\xc1\x25\x27\x55\x02\x39\x57\x53\x9a\x3f\xba\x48\xd5\x46\x4f\xce\x78\xe7\x3d\x2e\x58\x46\x6f\xbc\x70\xe3\x40\xd4\x8c\x81\x7e\x72\xed\x16\x2b\x83\xdc\x87\xa0\xa3\x10\xa8\xc7\x5b\x58\x45\x34\x4a\x9f\xdb\x22\x2e\xa7\x5e\x3c\x25\x19\x5c\xfa\xe4\xb7\x15\x6a\x7e\x2d\xc9\xb0\xec\xba\x09\xb6\xcc\x46\xac\xf7\xbe\x1a\xaf\x17\x69\xb5\x43\xff\x93\xc0\xb3\x73\xbc\xea\xba\xc0\x56\x8c\x3a\x3e\x3b\xdd\x92\x00\xb6\x8d\x84\x45\x34\xc4\xd6\xb1\x9f\x8e\x44\x11\x4d\xaf\x57\xff\xf1\x38\xa2\x69\x1b\x0f\x47\x12\xfd\xb3\xd6\xe3\xf9\xcb\x4f\xae\x78\x7a\x0b\xca\x15\xcd\x5d\x87\xfa\x0f\x18\x6a\x89\xa4\x74\x18\x93\xbd\x7d\xd4\x52\xab\x75\x9c\xa1\xef\xf8\xb5\xf6\x3f\x6e\xaf\x8d\xae\x03\xff\x0e\x8b\x6d\x3c\xe3\x40\x0c\x8e\x46\xe5\x10\xc2\x06\x81\x38\xc8\xf5\x98\x74\xec\xa5\xe2\x88\x67\x8c\x65\xe8\x49\x4c\x2b\x66\xfa\x60\x95\x38\xc2\x35\x1c\xa6\x53\xff\x7d\x4c\xa8\x69\xc9\x12\xdb\x2a\xe6\x92\x2f\x07\xb8\x1e\xb1\xbf\x3d\x14\xe9\x3a\x1e\x25\xf3\x1a\xf7\xf0\x64\x38\xc8\x07\x6b\x84\xc7\x6c\x6c\xe3\xfe\x8f\x44\xbf\xce\xdb\xb8\x58\x71\x38\x98\xaa\x8b\x43\xd9\xf0\xe7\x15\x36\xf6\xc1\x19\xbe\xc4\xbd\xe4\x19\xae\xc7\xdc\x80\xf7\x24\xfb\xf1\xa0\x39\x36\x5e\xb8\xf7\x42\xef\x46\xda\xcd\xca\x51\xbe\x67\x7d\xb8\xd8\xb1\x97\x50\x55\x0f\x24\xbf\x21\xee\xcc\x96\x8c\xeb\xc7\x7d\xc4\x31\xbf\x96\xeb\xcc\x8c\x17\x48\xb8\x7c\xc2\xda\xaa\x44\x08\xe6\x99\xa4\x5c\x89\x3a\xde\xf4\x8a\xbf\x1f\x84\x5c\xdf\x7e\x0e\x4b\x93\xcf\xd5\x53\x4f\x71\xcd\x51\x6c\xb4\x28\xf7\x7b\x5e\xc2\xdc\xdd\x67\xe4\x65\x12\x40\x15\x37\x75\x54\x90\x90\x7f\x1c\xb7\x25\x0f\x61\xe9\xe9\xf9\xae\x39\x24\x72\x74\x2e\xf8\xc6\x71\x2a\xd7\x8d\x35\x27\x1e\x92\xe4\xb1\x8c\xa2\x97\x14\x30\x07\x12\xd3\xe5\x4e\xc2\xb4\x7c\x14\x96\x89\x93\xc3\x05\x64\xda\xeb\x01\x2c\x80\x42\x6a\x40\x24\x1d\xcb\xf5\x21\x71\x2c\xb4\x55\x08\xb0\xbe\x5b\x91\x44\xa3\x7e\x43\x88\xdf\xd3\x31\x8f\x73\xd2\xdd\x89\xd9\x0f\x70\x99\x8c\xa3\xed\x84\x1f\xee\x6c\x1c\xf2\x56\x9f\x1b\x87\x7b\x08\xd2\x8f\x23\x84\xf8\x3d\xe3\xe0\x5e\x9e\xf2\xdb\xd9\x58\xc4\x87\xc6\x43\xca\xa1\xde\x8d\x0b\xad\xd3\xdd\x78\x88\x3e\xae\xf1\x3a\x38\xaf\xe1\xe1\x29\x46\xf2\x07\x9b\x8f\xa6\x07\xa7\x94\x88\xa3\x61\x46\x44\x10\x47\xdc\xec\x05\x8f\x2f\x6f\x71\x5e\x69\xd4\x74\xa0\x81\x8b\xcd\x83\xcd\x9d\x42\x3a\x2e\x2f\xd2\x41\xc6\xba\x50\xb9\x4e\x0a\xbf\x7c\xf0\x0a\x9c\x5d\xcd\x10\xf9\x2e\x3c\x32\x20\xe0\xd9\x4a\x16\xf2\x94\x8a\xdb\xe3\xcc\xea\x82\x5e\xa7\x8d\x39\x56\x0d\x28\xc7\xa2\xa7\x70\xc6\x3b\x43\xe9\x2c\x30\x66\x31\x53\x3e\x31\x99\x55\xbc\x59\x06\xb5\xcb\xef\x23\x07\x1b\x5f\x49\x61\x8d\x2c\xda\x35\xc7\x4f\xec\xe9\x50\xfc\x59\x2d\xef\x93\x38\x82\x39\xea\xae\x5f\x84\x5b\x7d\x4a\x20\x9e\xec\xd6\x6d\xce\xb6\x46\x5b\x6b\x66\x16\x01\x29\xa0\xc1\x1f\xdd\x2c\xdd\x4b\xb1\x9e\x1b\xc0\x83\x41\x0d\x3d\x7e\x88\x29\xfc\x81\x01\x80\x6d\x3c\x3c\x02\xb0\x05\x79\x65\x85\x86\x11\xb0\x80\x87\x06\xa2\x4f\xbc\xfe\xfe\x81\x80\x6f\xfc\xce\x81\x9c\xd8\x28\xf4\x6e\x7f\x51\xcc\xee\xff\x87\xc6\x37\x52\x77\x40\x9c\xd1\xe3\x11\x23\x82\x8f\x9e\xdb\x77\x44\x1f\xf8\x9a\xad\x59\x38\x18\xd4\xf7\xad\xc7\x99\x6f\xaa\xa6\x25\x84\x2a\x5b\xf7\xa1\x7f\x3c\x8e\x39\x67\x8f\x6d\xdf\xde\xab\x48\xc2\x93\x8b\x43\xde\xfd\x1d\x59\x51\xc2\xe0\x2b\x92\x07\x45\x3e\x01\xed\x9f\x8f\x7c\x37\x43\x9e\x1f\x16\xf7\x5f\x17\x7d\xc3\x61\xfa\xb6\xc3\x83\xef\x6a\xc4\xef\x89\x8c\x1f\x96\xe9\xe4\x16\xd3\xda\x64\x39\x7b\xe1\x35\xf1\xce\xf1\xab\x7b\xc2\xc1\x0e\x8f\x5a\xaf\xf8\x4a\x75\x53\x57\xe2\x57\xbd\x90\x14\xdf\xaa\x67\x53\x8c\xda\x61\xf8\x72\x9d\x8f\x9a\xf4\xb3\x83\x71\x91\x6d\x4c\x2a\x08\x48\x3a\x28\x0f\xde\x79\x40\xb4\x5b\x6b\x2f\x57\xf8\x16\x30\x12\x98\x30\x87\x60\x64\x3a\x0e\x34\x3a\x74\x73\x3d\x66\xec\x08\x49\xd5\x0d\xe4\x1e\xe3\x67\x26\xc1\x97\x99\x0b\xbe\xcc\x2c\xef\x3d\x9f\x04\x19\x11\xce\xc3\x82\xbd\x7b\xd1\x2a\xca\x8e\x0f\x3e\x9f\x8f\xf8\xfe\x38\x8b\x83\xfa\xa3\x8c\x7c\x35\xe9\x45\x36\x55\x5c\x4f\xc2\x99\xc2\x1c\x36\x26\xb2\x43\x24\x6a\x3d\xbe\x0b\x1a\x16\xc9\x13\x29\x51\x96\xbe\x29\x1b\xcf\x44\x6c\xaa\x61\xde\xb6\x59\xf3\xf3\x2e\x30\x42\xc6\xd3\x53\xd9\x39\x6e\xd3\xa2\xaa\xa2\x26\x10\xe8\x1a\xe6\xc0\x6f\xd0\xe7\x5d\x5c\x1b\x5b\x30\xcc\xd0\xbb\x81\x13\x40\xd2\xa9\xf3\xd5\x06\xf3\x5f\xcc\x11\x92\xa9\xc6\x8e\x98\xf4\x6b\x12\x33\x90\xf2\xee\x6f\x6a\xaf\xfc\xce\xc2\xf0\xe7\x04\xf0\xa8\x72\x50\xca\x01\x8a\x75\xa6\xd7\x65\x1b\xbd\x0c\xc4\xd1\x8a\xee\x6a\x6c\x7a\x89\x1d\xd7\x3d\x58\x29\x38\xc5\x38\xf2\x5a\xaf\xe3\x6a\x4d\x91\x38\x1e\x38\xce\x7c\xcb\x7a\x30\xaa\x67\x38\xf7\xba\x5a\xe7\xe5\x04\x96\x6e\xcc\x75\xec\x88\xe4\x77\xb5\x31\x1a\xa5\x87\x70\xcd\xfc\xf1\xa1\xc2\x7a\xc6\x37\x14\x60\x91\x8b\x06\x19\xb1\x35\x03\xf9\x42\x0b\xa3\x21\xce\x36\xf1\x07\x06\xc9\x0f\x91\xaf\x57\xee\xe1\xe6\x73\xbe\xb5\xdf\x2e\xf9\x2e\x04\x9f\x61\xa5\x3c\xa8\xdf\xd4\xb1\x05\x6e\xbe\xfa\x43\x23\xc3\x80\x58\xe7\x9e\x6b\xfe\xd8\xd8\xda\xb2\xbb\xaf\x57\x19\x5e\xd1\xee\x36\x1a\xe2\xf7\xa1\x14\x5b\xf9\xe3\x05\xe5\x3d\xcd\xf5\x42\x5a\x89\x8b\xf0\xdd\x63\x79\xd6\xe4\x9b\x15\xe5\xe3\x15\x6f\x3a\xe2\x9e\x80\x27\xa2\xb6\x09\x70\x24\x9e\xf5\xdf\x3e\xd8\xd1\x68\x2e\x01\x43\x0c\x70\xdb\x62\x28\x7d\xf9\xbb\x66\x10\x38\x21\xc3\x69\x30\x19\xe8\xee\x07\xaf\x08\xdf\xef\x62\xc4\x7d\xc3\x77\xf0\xf8\x1d\x06\x7e\x1c\x55\xc3\x29\xf4\x40\xb3\x57\xd2\xd5\x78\x74\x64\x42\x61\xbf\x0f\xac\xd0\xe3\x68\x14\x5f\x9e\x63\x78\x08\xc9\xf7\x1f\x86\x3d\x3e\xc2\xe3\x3e\xfc\xf0\x11\xbf\x43\xa6\x20\x4f\xaa\x64\xeb\xa6\x6d\x68\x79\x60\x22\xb6\x67\x56\x5e\x59\x5e\x37\x53\x01\x26\xf0\xfb\x6c\xd0\x2b\x3a\x56\xe7\x02\xd9\x24\x3f\xf0\x7d\x1d\x5f\xab\x6f\xfa\x7c\x6b\x75\xd8\x02\xb9\x52\xbb\xf5\x35\x17\x58\xad\x53\x2b\x08\x6a\x6a\x9d\x66\xc9\xf1\x74\xa8\xa2\xc0\x97\x9a\x13\xc0\xc2\xcd\xc1\x97\x64\x08\x5d\xc3\x3e\xe3\xa9\xe2\x7e\x85\x64\xa7\x6f\x91\x9d\x5e\x73\xf6\xb4\x07\x1b\x95\xab\x36\x1a\xd4\xb1\x7a\x37\x6d\x39\xa9\xf3\x92\xef\x8b\x8d\xe1\x0d\x73\x9b\x32\xdf\x4f\xf0\xf6\x9a\x32\x27\x58\x03\xe4\x14\x01\x80\x3d\x8e\x85\xb0\x56\x55\x40\xb1\x0a\x6b\xbc\xa1\xac\x63\xd0\x78\x65\x6e\x0c\x8f\xcf\xe3\x1c\xa9\xa1\x67\xf6\x78\x54\xea\xb3\x99\x8c\xaa\x59\xfe\x1d\x1f\x93\x51\xe8\x4b\xf9\x19\x40\x2d\x9b\xa6\xe7\x37\xbb\xf7\x2c\x6e\xad\x6e\x1d\x9a\x7e\xb6\x7c\x16\xb7\x56\xb7\x13\x4c\x09\xf4\x14\x55\x02\x7d\x1c\x57\x3b\xbe\xac\x4a\x7d\xb5\xc3\xaa\x1f\x68\x83\xba\x0e\x2f\xae\xf8\xe2\xeb\x95\x2b\x98\xf4\x38\xa9\x19\x52\xe8\xb8\xf2\x5c\xcf\x2b\x12\x22\xca\xd9\xae\xcf\xb8\xe4\xc1\xbe\x27\x75\xc3\xce\x27\xd5\xe7\x76\x0a\x5e\x11\x63\xa3\xf3\x72\x58\xdd\x96\x3d\xc7\xe4\x6e\x32\x78\x98\xc3\xb6\xde\x1b\x58\xfa\x33\xc0\xd2\xd7\x04\x96\x5e\xcb\x17\x61\xa6\xad\xd2\xa1\xb3\x2b\xfb\x1c\x91\x02\x41\x2b\xaf\xce\x68\x05\x38\xbb\xc8\xe7\x6a\xc1\x3a\x93\xa9\x94\xad\xbb\x90\x05\x9f\xa0\x05\xfd\x56\x8d\x08\xde\xa7\x0e\x64\xae\x35\x56\x03\xe4\xf4\x5b\xdd\xaf\xe4\x89\x2c\x56\x0c\x68\x0c\x1f\x24\x27\x80\xc5\xb3\x2a\x04\x6b\x3c\x12\x4e\x71\xbc\xaf\x42\xe0\xd7\x31\xa3\x14\x0e\xe6\x81\x85\x71\x11\xdc\xfb\x7c\xe8\x66\x01\xf7\xb9\x6c\xa6\xa3\x90\xd6\xbd\x01\x5a\xcf\x63\x38\xed\xb4\x13\x54\x0a\x5b\x11\x4d\x4d\x62\x37\xf5\x0d\x14\xfb\x5a\x1d\x42\x37\xed\x05\x14\x7c\xb3\x4e\x60\xbf\xf8\x09\x06\x05\x13\xe9\x15\x32\xab\xe4\x98\xbc\x85\x07\x42\x2d\x6d\x65\xb0\x44\xa9\x4d\x4f\xf3\xa2\xef\x41\x68\x9e\xdd\x5c\x71\xf7\xef\x34\x3f\xbc\x48\xa6\x2d\x42\x30\xb5\x90\x95\xf8\xa9\x6d\x8d\x5c\x11\x40\xb9\xf4\x2d\x9e\xa4\x6d\x58\x19\x4a\x83\xfb\x58\x59\xd4\xc0\x5b\xe8\x13\xc1\xdc\x8e\x3e\xb6\x67\xaf\x64\xfc\xce\xf7\xf6\xfc\x6c\x02\x1c\xc3\xd1\x1d\x63\xb7\xea\xb2\x10\x9d\xe3\x47\x36\xf2\x11\x7a\x19\x5c\x31\x1c\x81\xc2\xf3\x1d\x7e\x5c\x22\x70\x3f\x1a\xca\xe1\xe8\xc3\x47\x6d\x34\x50\x6a\xd2\x42\x50\x27\xf8\x12\x10\x87\x9b\xca\x75\x8f\x39\x14\x79\xeb\xa0\x61\xc8\xbd\x5b\x08\xe8\x07\x5d\x4b\x31\x2e\xe6\x9f\x53\xfd\x7f\xf2\xa2\x6c\x38\x00\xff\xae\xec\x91\xfe\xff\x25\xef\xca\x8e\x2d\xb3\xee\x61\x59\x3c\x9c\xb9\x40\xf0\x75\xbc\x8f\x23\xc7\x55\xb4\x9f\x51\x23\xdc\xa7\xc8\x88\x5d\xf9\xc8\xf2\x66\x5f\xb3\xf8\x8a\xd5\x06\x5b\x74\xdc\x5f\x10\x2f\x1f\xf5\x26\x35\xa6\x8f\xb7\xc4\x43\x90\x9c\xa9\xb7\x48\xf2\xd5\x1a\x91\xea\x7b\x03\xa5\x5a\x8f\x16\x30\x49\xa8\x8b\xc6\xf2\x26\x1f\xbd\xe4\x4d\xad\x5b\x7b\x34\xe4\x78\x73\x47\xa3\x96\x4a\x72\xcf\xd2\x42\xf1\x67\x99\x89\x02\x06\x53\x91\x9c\xf0\xde\xb2\xe4\xc8\x43\x8a\x78\x97\x5c\x52\x9a\x3f\x8d\xc2\x08\x46\xac\xcd\xc4\x5d\x07\x8d\x02\x68\x96\x57\x05\x63\x19\xc7\xff\x49\x6e\xf8\x8d\x4b\xc9\xd1\xcf\x05\xe2\x4b\x81\x92\xb3\x44\xfc\x10\xa2\xdc\xd8\xf8\x74\xfe\xce\xba\xed\xfb\xb6\x5a\x0e\xfd\xfc\x13\xa1\xae\x74\x02\x6d\x6e\x7f\xa6\xdd\xf4\x0b\xb0\xdd\x60\x0d\x5f\x0d\x5f\x6a\x77\xf4\xf1\x87\x11\x9c\xdc\xce\x4e\xdd\xb3\x02\x2f\xf1\x5b\x0b\x77\xcc\x23\xb3\x8e\xbf\x4a\x7b\x41\x2c\xa6\x48\xaf\x4e\xb5\x04\x1f\x05\x54\xeb\x08\xbe\x1d\x78\x74\x15\x18\x72\xf2\x91\x41\x5f\xa4\x78\x45\x51\x80\x5c\x7d\x6a\xb4\x97\x57\x20\xe5\x99\xcd\xeb\xb7\x57\x94\x5c\xb5\xf7\xe2\x30\xd2\x75\x61\x8f\x81\x7e\x8a\xcf\xde\x5e\x3f\xbd\x70\x1f\x3b\x0c\x56\x5a\x9b\xe4\x0f\xa9\x65\xc1\x37\x82\xb5\x71\x1a\x7f\xa3\x9f\x09\x52\x83\xa9\xd2\x2a\x3f\x54\xcd\x17\x62\xf7\x9d\xb5\x13\x5c\x04\x1d\x91\xbd\x3e\x49\xaa\x2b\x30\x39\x8c\x62\xcb\x2d\x0e\x1a\x77\x28\x85\xf4\x1e\x9e\x95\x51\x07\xbf\xf3\x01\xd1\xb0\xad\xe0\x50\x79\x60\xac\xb3\x77\xb9\xe2\xd7\x6f\x42\xc0\x4c\xf6\x9f\xbd\x7a\x15\x35\xec\x9c\x4c\xd3\x0a\xd1\xf3\x57\x51\xa5\xf9\x30\x80\x87\x1e\xbe\x12\xa3\x80\x29\xe3\xce\xe6\xad\xca\x78\x6c\xfa\x56\xd8\x87\xbe\xb3\x1a\x80\xdc\x89\x6b\x2d\x80\xb0\x2f\x44\x07\x40\xf3\xdf\xf9\x54\x80\x31\x4f\xd1\xec\xd1\xe7\x1f\xa3\xef\x3e\x5a\x4d\xfb\x8c\x55\x33\x88\xb6\x8d\xcf\xcc\xe9\x1d\x8e\x0f\xc8\x64\x41\xcb\xc0\xe7\xbe\xb5\x1a\x14\x69\x47\x5c\x14\x76\x82\x13\x8a\x3f\x3c\xf7\xe0\x77\x61\x0d\xc1\x6c\x72\x5f\x65\xf2\xf4\x49\x50\x07\x06\xff\x15\xc2\x78\xa7\x95\x68\xdc\xd3\x1a\x34\xee\x23\xe0\xe2\x04\x36\x7e\x7e\x85\x5f\xc2\x42\xdc\x88\x39\xb4\x4c\xa9\xc8\x26\x2c\x79\xe3\x77\xf5\x43\x1c\x14\x4b\x4f\x18\xee\x5b\x7d\xb3\xa4\xe1\xbf\x75\x1c\x76\xcb\x5f\x29\x0e\x0e\x02\x9f\x1b\x1e\x69\x3e\x37\xfc\x18\xb2\xcf\x9d\xfb\x3a\xf1\xb4\xd4\x7b\xe6\xbf\xe1\xd8\x94\xaf\xf7\xf2\xc1\xe6\xee\x6b\x7c\x92\xf2\xdb\xa0\x46\xf8\x65\xe3\x38\x77\xdc\x86\x7e\x48\x71\xd4\x84\x31\xcb\x68\xcb\x54\xab\x23\x88\x71\xdf\x53\x8b\x5e\x9a\x05\xfa\xe5\xbb\x9c\x7a\xac\x44\x1f\x52\x1d\x13\xb3\x67\xb6\x8e\x94\x43\x46\x6b\x03\xe3\x90\xf6\xe8\x0b\xa3\xfa\x55\x2b\x8d\x6d\x77\xdf\x70\xfb\x19\xd9\x7e\x84\xb3\x9f\x0f\x1d\x7f\x37\x94\x83\xce\xad\x4a\xfc\xa1\xd7\xe9\x17\x5e\x15\xcc\x9e\xbb\x86\x45\x60\xf2\x32\x36\x4c\x01\xfa\x30\xb6\x31\x06\xb9\x42\xc2\xf1\xdd\xd9\x56\xcd\xdf\x72\xcd\x04\x51\xde\xe9\x5b\xd8\xbb\xdd\xb8\xa3\x8f\x4d\x45\x95\xe4\x1b\x57\xee\x83\x36\xd3\xca\x76\x1b\xca\x2d\xa2\xdd\xee\x98\x5d\xc4\x5f\x87\x72\xa0\xc6\xe5\x2b\x54\xfc\x82\x14\xfd\x4c\xdf\xe2\xa7\x5b\x2b\xb9\xb6\x01\x6d\x58\xbe\xb0\xaf\x17\x39\xa0\x14\x53\x8e\x5b\xa5\xdb\x6a\xcf\xc7\xb2\x7e\x47\x83\x17\x87\x72\x70\x36\xff\x19\x39\x21\x92\x43\xce\x7c\x81\xdf\xf3\x03\x54\xd8\xa9\x14\x18\x97\x1b\x41\x11\x9d\x37\x01\x31\xbd\xfe\xe5\xed\xe5\x08\x72\x66\x83\x6a\xc9\xcc\x86\x8e\xbf\x32\x1c\x6e\x5f\x71\xe5\xb8\x29\xc0\x7d\x33\x3f\x03\x81\x3c\x3a\x01\xa1\x21\xef\x99\x05\xf1\xcc\x36\xa4\xd4\x56\xe4\x7b\xd9\x31\x4a\x67\xf2\x3b\x06\x0a\x9e\xd5\x13\x28\x7b\x55\x6f\xd2\x6b\x1d\xf6\x59\x8b\x1b\xc2\xf3\x03\x09\x11\x08\xf8\x81\x84\xda\xce\x0e\xcf\xa0\x49\x65\xbd\xab\x0a\x15\x1c\x05\xfe\xbd\x66\x19\xa8\x81\xf8\x96\x0d\x42\x9b\x76\xc3\x24\xc2\xad\x9c\xf4\x76\x86\x5f\xd1\xd2\xe9\x46\xe4\xfd\x22\xb0\x7e\x1b\xf2\x3b\xdb\x52\xc3\x80\xd7\x2b\x87\x18\x33\x28\xbd\x3a\xf3\x0f\x0e\xc2\xf6\x34\x9a\xcc\xb6\xba\x29\x9d\xa5\x4a\x67\xf3\x96\xf2\x22\x60\xfe\x3c\x78\x67\x17\xce\xe4\x4b\x67\xfc\x81\xe1\xd1\x24\xc2\xa6\x74\x26\x93\x96\xf6\x15\xac\x87\x01\x5e\x24\x63\x1e\xe3\x06\xad\x7c\x3b\x00\x57\xc6\x3d\x66\xb7\xf6\xad\x8f\x60\x87\xf8\x87\xf7\xfd\xf9\xec\x7a\xe7\x73\x79\xb6\x67\x86\xd2\x93\x8b\x61\x70\x72\x59\xb4\xc0\x62\xd5\xca\xf3\x16\xfc\xef\x9a\xfd\xb8\xae\x24\xdc\x7b\x96\xd7\x11\xed\x15\x83\x5c\xb6\xd1\xa4\x87\xf7\xd1\x05\x82\x26\x2b\x98\x79\xc7\x29\x06\x28\x7f\x2b\x57\x43\xe0\x56\xf8\x45\x7e\xab\x1d\xcf\x37\xd3\x58\x70\xe0\x50\xe3\xa5\xa9\xf7\x92\x13\xc0\xcc\x3d\x6f\x63\x43\x47\x88\xa3\x85\x3a\x1e\xed\xdf\x75\x0f\xf5\x87\xa1\x2c\xe2\xc2\xa2\x1c\xe4\x67\xb6\x95\xbb\x17\xa3\x20\x0c\x83\x0d\xa5\x90\x30\x2f\xfb\x2e\x92\xd3\x5c\xd9\xcc\xc0\xad\xa8\xc1\x37\xb0\xf7\x8b\x00\x16\xa2\x78\xf0\x06\xb4\x8c\x41\xca\xbf\x14\x62\x95\x7c\x92\x98\x86\xcf\xa3\x57\x41\xcd\xfc\x18\x84\xd1\x44\xf7\x7f\x1e\xc9\xdb\x5c\x72\x49\xca\x2a\x71\x04\x91\xbc\x2d\x16\xc0\x3e\xed\xda\xd5\xd3\x47\xe1\x8b\x5e\x6c\x11\xf2\x00\xfc\x02\x18\x17\xfe\xa0\xcf\x7d\xe9\x38\x60\xd4\xa0\x36\xff\xa6\x2f\x85\xc9\xef\xb0\x5d\x31\x7b\x48\xd3\xdd\x7f\x72\xad\xff\x2d\xd1\x60\x0b\xdf\x84\x66\xe0\x05\xf0\x3f\xd2\x90\x7b\x23\x41\xe7\x67\xbf\x47\x78\xc1\x95\x54\x46\x88\xdc\x4d\x1d\xbf\xc4\xae\xa8\xc2\xcd\x56\xbe\x89\xe3\xf1\x44\x3f\x1e\x46\x54\xd4\xd4\x04\x51\xcd\x8e\xef\x20\x66\xdf\x67\xfe\x79\x41\x5c\xc2\x93\x82\xaa\xd3\x57\x89\xe4\x99\xfb\xef\xdd\xd3\x82\xc9\xa7\xbe\x69\xb6\x9f\x93\x7c\xcd\x73\xa2\xbf\x09\xde\xee\x94\x78\x5d\xc4\xa4\x51\x32\x91\x9f\x9c\xfa\x8e\x1b\xfe\x8e\xb4\x54\x62\x20\x78\x1a\xeb\xbb\x1d\x32\xe4\x33\xab\xc8\xd8\x20\x83\x1f\x7d\xc5\xcf\x02\x3f\x8b\xfc\x1e\xbf\x0e\xf8\x75\x28\xcb\x5b\xa9\x0c\x0e\x43\xd5\x49\xeb\xdb\x20\xe7\x1e\xbf\xf9\xad\x27\x7c\xe3\x1a\xfd\xe8\x7b\x6a\xf6\x03\x0f\x72\xc9\x57\x5d\x91\x6f\x3f\x28\x5f\xbe\x58\xf0\xdc\x7f\xbc\xe0\x11\xfb\xc7\xee\x35\x0b\x29\xca\xe1\xee\x35\x4b\x92\x8f\xc0\x26\x48\x97\xd5\x06\x25\x4d\xb9\x3c\x0e\xcd\x94\x24\xe5\xb5\xf9\x21\xf3\xe3\xd2\x14\x72\xfd\xa8\x34\x95\xfc\xdf\x00\x00\x00\xff\xff\xec\x67\x37\x56\x9b\x89\x00\x00") +var _confLocaleLocale_enUsIni = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xc4\x7d\xeb\x72\xdc\x46\xb2\xe6\x7f\x3c\x05\xec\x0d\xad\xec\x08\xaa\x15\xb6\x63\x2f\xe1\x90\xe4\xa5\x49\xeb\x32\x47\x24\x75\x44\x6a\x66\x67\x15\x0a\x0c\xba\x01\x76\x63\xd8\x0d\xb4\x01\x34\xdb\x3d\xbf\xf6\x35\xf6\xf5\xf6\x49\x36\xf3\xcb\xcc\xba\x00\x68\x4a\x9a\x73\x62\xcf\x1f\xb2\xba\x2a\xeb\x96\x95\x95\x95\xb7\x2a\xe4\xdb\x6d\x56\x94\xdd\x22\x7d\x9e\x9e\xa6\xdb\xbc\xaa\xd7\x65\xd7\xa5\x5d\xb9\xbe\x7d\xb2\x6a\xba\xbe\x2c\xd2\x57\x55\x4f\xbf\xdb\xfb\x6a\x51\x26\xc9\xaa\xd9\x94\x04\xfa\x9a\xfe\x25\x45\xde\xad\xe6\x4d\xde\x16\x94\x71\x6e\xe9\xa4\xfc\x63\xbb\x6e\x5a\x06\xfa\x4d\x52\xc9\xaa\x5c\x6f\xb9\x0e\xfd\x4b\xba\x6a\x59\x67\x55\x4d\x3f\xaf\x29\x95\xbe\xa9\x93\xae\x59\x54\xf9\x3a\x0b\x0a\x90\x61\xe5\x3f\xa7\x3f\xd6\x45\x7a\xdd\x97\xdb\xf4\x59\xb7\xc9\xd7\xeb\x17\x79\x87\x2a\x7d\x99\xe6\x8b\x45\xb3\xab\xfb\x67\x4f\xa5\x40\x1a\x6f\x76\xbd\xb5\x7e\xb5\xeb\x25\x6f\xb7\xb5\xac\x0f\xdb\xa4\x2d\x97\x15\x4d\xac\xa5\xac\xf7\x9a\x4c\xf6\xe5\xbc\xab\x7a\x1e\xf4\x5f\x24\x95\xdc\x97\x6d\x57\x35\x3c\x9e\x3f\x4b\x2a\xd9\xe6\x4b\x06\x78\x47\xff\x92\xbe\xdc\x6c\xd7\x39\x2a\xdc\x68\x32\x59\xe7\xf5\x72\x27\x30\x6f\x35\x99\x24\x3b\xc2\x5c\x9d\x03\x67\x1f\x34\x99\x94\x9b\xbc\x5a\x33\x7e\x9e\x70\x82\xda\xed\xba\x7d\x03\x2c\xbe\xd3\x24\x8d\x31\xeb\x0f\xdb\x12\x43\x7c\x72\x43\xa9\x64\x91\x6f\xfb\xc5\x2a\xa7\x9c\x33\x49\x25\x04\xb4\x6d\x68\xac\x4d\x7b\x00\x9c\xfd\x48\x9a\x76\x99\xd7\xd5\x3f\xf2\x5e\xc6\x7f\x15\xfc\x4c\x36\x55\xdb\x36\x3c\xf5\x0b\x24\x92\xba\xdc\x67\xdc\x0e\xe5\x5c\x96\xfb\xb0\x15\x2e\xd9\x54\xcb\x56\x66\xc9\x85\x17\xf8\xc5\xad\x70\xd9\x6d\xd3\xde\x69\xc1\x4b\x4e\x0e\xaa\xd2\x20\xb4\x34\xee\x3f\xaf\x09\x2f\x5a\x7a\x81\x1f\x11\x40\x97\xe4\xc5\xa6\xaa\xb3\x6d\x5e\x97\x8c\xa3\x53\xfe\x45\x78\xa1\x5f\x89\x2e\x77\xd6\x95\x7d\x5f\xd5\xcb\x8e\x8b\x25\x2b\xbd\xd6\xac\x24\x28\x73\x79\x3c\x9e\x2e\xbb\x2d\xcb\x42\x46\xd4\xa5\x2f\x29\x9d\x6c\x77\xeb\x35\xcd\xfd\xf7\x5d\xd9\xf5\x0c\xff\x8e\x7e\xd3\x2c\xe4\x77\x52\x75\x1d\x25\x28\xfb\x0d\x12\x09\x2d\x40\xbd\xc0\x90\xce\x90\x48\x92\x8f\x5d\x99\xb7\x8b\xd5\xa7\x44\xfe\xa3\x47\x4e\xcc\x66\xb3\xa3\x4b\xc3\xe4\xa0\xa4\x20\x3d\x58\x07\xc9\xa2\x29\xf8\xc7\x19\xfd\xa3\xa6\xab\xba\xeb\x89\xa4\x3f\x25\x9a\x60\x30\x49\x09\x1a\xfb\xaa\x5f\x97\x3e\x13\xfb\xa3\xe3\x75\x48\x5f\x56\x6d\xd7\x3f\xe9\x2b\x22\xb9\xf7\xbb\x3a\xe1\xf9\x11\x39\x67\xc5\xdc\x76\xf9\xab\x86\xb0\x83\xec\x96\xe6\x77\x71\xb8\xfe\xd7\xb7\x27\xe9\x3b\xda\xea\xcb\xb6\xa4\x74\x4a\x6d\xd0\x3f\xaa\xf3\xd3\x2c\xa1\x5a\xd6\xd3\x79\xde\xe7\xf3\xbc\x2b\x3d\x5a\xb9\x50\x68\xd4\x95\x81\x52\x99\x6d\x80\x45\x74\x7d\x34\xdf\x29\x3a\xa7\x36\x74\x77\xb8\x36\x2e\x79\x8b\x50\x3e\x73\x0d\x54\x7e\xb7\x2e\x39\x9f\x9a\x4a\xdf\x5c\x5e\x5e\x9d\xff\x9a\x96\xf5\xb2\xaa\xcb\x74\x5f\xf5\xab\x74\xd7\xdf\xfe\xf7\x6c\x59\xd6\x65\x4b\x4c\x64\x51\xa5\xb4\x33\x5a\x22\x82\x94\xc8\x53\x26\x37\x4b\xba\x6e\x9d\x6d\x04\xbd\xd7\xd7\x6f\xd3\x0b\x46\xf1\x36\xef\x57\x18\x48\xbf\x4a\xba\xdf\xd7\x8c\x22\xd7\xe1\xcd\xaa\x4c\x6f\x2b\x9a\x35\x80\x9a\x5b\xc3\x47\x5a\xe8\x18\x67\x49\xd9\xb6\x19\xed\xfb\xfe\x90\x69\x65\x6d\x6f\x08\x29\x4d\x10\xe9\xd4\x4d\x9f\xce\xcb\x14\x75\x66\x49\x62\x03\x36\xec\x9e\x6e\xb7\xeb\x6a\x21\x3b\xf6\x95\x94\x79\x44\x33\x8b\x56\x2c\x85\x70\x40\x94\x95\x05\xe8\x22\xfe\x77\x68\x76\x6d\x1a\xb1\x01\xd4\x5f\x95\xc4\x97\x57\x3b\xda\x72\x39\xf1\xd4\x75\xb3\x2b\xbe\x01\xa5\xda\xe8\x3d\xa1\xa6\xef\x1b\x1a\x30\xb0\xe3\x00\x7c\x17\xa7\x44\x71\x7c\x2a\xb4\xe5\xa6\x21\xee\xe0\x88\xbd\x22\x82\xda\x57\x54\x48\x33\xed\xf2\x7b\xda\x6f\x7d\x93\xf6\xab\xaa\x4b\x0b\x22\xb6\x05\x37\x4c\x5b\x63\x47\xfc\x58\xc8\x82\x08\x54\x48\xc3\xf2\xe2\x35\x00\xd4\x66\x47\xd4\xb4\xa2\xc6\x98\xdb\xf3\xd1\x44\x4d\x4e\x8d\x13\x53\xa2\x76\x40\xdf\x44\xb9\x0d\xf1\x56\xe6\x7e\xe7\x48\xe8\xef\xb0\x7d\x1a\x55\x7e\x7b\x4b\xa3\xea\x88\x2a\x5e\xa7\x8b\x75\x43\x24\xf5\xe1\xfd\x5b\xaa\xbc\xea\xfb\x6d\xb6\x6d\x5a\x90\xf1\xcd\xcd\x3b\xda\x1e\x6d\xef\x73\x03\x5c\x33\x4c\xbd\xdb\xcc\xe9\xd7\x7e\x55\x11\x13\xc8\x83\x05\x02\x2a\xd6\x7c\xc0\xd4\x69\x53\xcf\xb0\x56\xbb\x76\x3d\x58\x46\xea\xd2\x4a\x8e\x0c\x8f\x87\xf0\x94\xff\x5c\xfb\x51\x62\xba\x1d\x9d\xc2\x7b\x2c\x2a\x4d\xb5\xc4\x69\x42\xb4\xd5\x6c\xb9\xdd\x80\xb8\xae\x34\xc3\x53\x14\x4e\x20\x57\x2e\xe7\x10\x95\xe2\x8c\x0f\x78\xe9\x86\x26\xac\xbb\xf9\xfa\x82\xd0\x80\x2d\x8d\xdc\xdb\xb6\xd9\x50\xee\x4b\xfa\xe7\x33\xfc\xf0\x2f\xb8\x3d\xc0\xe4\x45\x41\x6c\xa6\x3b\x49\xdf\xbf\x3c\x4b\xff\xcb\x4f\x3f\xfe\x38\x4b\xdf\xf4\xbc\x21\x98\x46\xfe\xce\x6b\x4b\x49\x39\x10\x1d\x28\xed\xdc\x9e\x96\xff\x5b\x26\xf0\x6f\xd3\x67\x28\xfd\x1f\xe5\x1f\x39\x9d\xb3\xe5\x6c\xd1\x6c\x5e\xf0\xe6\xde\xe4\xfd\x2c\xe1\x12\xa2\x1a\x25\xa7\xeb\xb2\x2e\x28\xa1\xc7\xaa\x96\x05\x5c\x47\xcb\x83\x43\x56\x4e\xff\x6c\xd1\xd4\xb7\x55\xcb\x13\xfa\xad\xce\xe7\x84\x13\x93\x0b\x88\x1d\xa3\xc4\xce\x2e\x42\x1a\x6d\xe4\xea\xf6\xe0\x41\x31\xd5\x4b\xce\xd4\x05\x4d\x58\x56\xa2\x46\x55\x64\x72\x58\xbe\x46\x36\xd6\xed\x8a\xa6\xd7\x1a\xbe\x3b\x8f\xf0\xe6\xf6\x76\x4d\x8c\xcd\x98\x95\xf6\x70\x25\xb9\xc2\xb7\x42\x10\x22\xc6\x2d\x24\x9b\xf3\xaa\x03\xe4\xd9\xf9\x65\x5a\xde\x13\xb5\x11\x39\x6c\xdb\xa6\xd8\x2d\x40\x61\x0c\x7b\x92\xf2\x31\x41\xf8\x25\xce\xb0\x10\xf6\x16\xec\x55\x1e\x1a\x33\x84\x05\x01\xd1\x16\x2d\xa4\xbd\x4c\x10\xd4\x9a\x20\x61\xdd\x5c\xb3\x70\x18\x96\x4d\x56\x18\x8d\x0e\xab\xd4\x0d\xeb\xd2\x72\xd7\xeb\x43\x8a\x53\x1f\x74\xb1\x68\xcb\x40\xb6\xeb\x66\x89\x9e\x55\x26\x21\x66\xf7\x15\x09\x15\xc1\x52\xa1\xd4\xc4\x45\x66\x0f\x7f\x66\x00\x16\xd3\xba\xc9\xba\x6e\x60\x57\xdc\x31\x97\xd0\xdc\xa9\x73\x1e\x5f\x87\x21\xa0\x07\x16\xf7\x88\x18\xef\x2b\x70\x1a\x45\x16\xc6\x4a\x18\x43\xd7\xd4\x55\x57\x96\x68\x81\xea\x3f\xa5\x36\x51\x67\xa6\x22\x8c\x8a\x22\x76\xee\xfe\xb5\xd9\xa5\x45\x93\xf2\x41\x00\x76\x46\xb5\x6d\xaa\xb5\x4e\x5f\xe7\x9c\xb6\xd5\x72\x45\x7c\xa5\xd9\x9f\x08\xd2\xf6\xab\xa6\x64\xda\x79\x73\xfe\xfc\x07\x19\xc7\x92\x99\x9b\xab\xc4\x6c\x31\xdf\xf5\x0d\xd3\xa9\x2e\xa1\x0c\xc1\x1d\x2f\x80\x1c\x09\x4b\x02\x34\x14\x4f\x4d\x00\x1b\x9f\xd6\xba\x4f\xc2\x32\xdd\x20\x1e\x46\x6a\x0f\x44\x5c\x95\x62\xb2\x65\x03\xc9\xcc\xa4\x16\x66\xd5\x24\x4a\x77\x7d\xb6\xac\xfa\xec\x96\x37\x2c\xb7\xf9\x92\xeb\xf2\xc9\x41\x25\xe9\x63\x2a\x7a\x9c\xd2\xae\x27\xc9\xb1\xf8\x39\x7d\x74\xaf\xc7\xf5\x4f\xbc\x13\xb3\xfc\x9e\x60\xb1\x18\x40\x70\x4b\x14\x2e\xd2\x82\x89\xef\x45\x43\x74\xce\x38\xef\x76\x5b\x70\x74\x3d\xa1\x4f\xd2\xad\x00\x16\xcd\xbe\x5e\x37\x79\x01\x96\x43\xbb\xab\x82\xf2\x31\xaf\xea\x9c\x4e\x17\x6b\x05\xac\xec\x11\x51\xc3\xe5\xd5\x0d\x00\x97\xcd\x7c\x57\xad\x0b\x03\x98\xd1\x0c\xef\xf3\x75\x55\xb0\x9c\xa5\xeb\x1e\xca\x34\x96\x55\xc9\x58\x16\x4d\xcb\xc7\x21\x66\x63\x15\x8f\x9c\xc3\x2d\x9f\x6f\xc8\xa6\xba\x0a\x8b\x7a\xee\xc8\x64\x34\xd0\xc2\x43\x00\xe5\x03\x15\x14\x53\x75\xf5\xe3\x1e\x23\x5d\xec\xa8\x2f\x5a\x74\xce\xa6\x8a\x5d\xfa\xe4\x05\xfd\x4d\xf8\x78\x16\xbe\xb7\x1c\x23\x9e\x0b\x53\x29\xdc\xc9\x2e\x8d\x86\x1a\x91\xb7\xa3\x2e\x23\xde\x60\xae\xe1\x78\x8d\x04\xba\x9d\xd0\x2b\x6b\x5a\x6b\x5a\xd6\xf2\x1b\x4a\x3c\xa6\x0d\xbc\x5c\x63\x11\x72\x48\x2f\x24\xc6\x35\x84\x37\x26\x90\x13\xd9\x2e\xb7\x34\x35\xe6\x9d\x7d\x7e\x47\x63\xcb\x5b\x12\xc2\x92\x8f\xac\x8d\x7e\x4a\x76\x22\x00\x35\xeb\xc2\x09\x9b\xa0\xe9\xa6\x1d\xaa\x58\x1e\xc8\xd1\x6b\x47\x52\xe4\x62\x95\x39\x5d\x96\x91\xd2\x97\x7f\xe0\xcc\x43\x91\x57\x6d\x99\xd8\xb9\x28\xd9\x1c\xb0\x5c\x3c\x89\x8b\x83\x5f\x2d\x12\x7f\x68\x8b\x90\x88\x3e\x6f\x18\x6b\xf7\xa5\x83\x3a\x0b\x73\xe3\x0a\xd4\x16\x09\x6a\xda\x54\xac\x09\x51\x91\xa8\x6b\x5a\x2a\x2a\x1b\xa9\x22\x1f\x55\xc7\xfe\x94\x58\x07\x51\x93\xc9\x47\x62\x06\xa4\x97\x08\x7b\xc9\x58\x1b\xb3\xc5\xa1\xa1\x08\xcf\x61\xc5\x4c\xf9\x81\x3f\x07\x57\xe5\x96\x8f\xcc\x4d\x87\x55\x5d\x13\x64\x71\x50\xd9\xcb\xad\xef\x2f\xc2\x69\x69\xc1\x89\x3f\x7d\x63\xda\xfb\x57\x36\xf1\x6b\x45\x2b\x89\xfa\xf1\xc9\xc1\xe7\x35\x6d\xb5\x2d\xb0\x4f\x9b\xe4\x70\x92\x46\x67\xd0\x2a\xef\x88\xfb\xd2\x01\xa7\xd5\x8a\x99\x69\x07\xbc\x6a\xf9\x42\x48\x1e\x9a\x3c\x88\x54\x6a\x36\xed\xf0\x48\xe3\x11\x0a\x83\xd2\x5e\xdc\x81\x8f\xe3\x3c\x3c\xf5\x27\xfa\x24\x84\x6d\x4a\x96\xf9\xb2\x8d\x68\xe8\xf2\x2b\xbd\x28\x13\x12\x4c\x96\xb4\x1f\x8d\xde\x9e\xb3\x4a\xb6\x84\x84\xaa\xe4\xc6\x00\x65\x1f\x72\x50\x85\xb0\x9c\x5f\xcc\x62\x41\x1b\x7b\x0f\x7d\x95\xb6\xe6\x08\xfd\x74\xd6\x50\xf1\xcc\x38\xb2\x1c\xb8\x90\x4f\x3a\xda\xec\x1e\x89\xa7\x29\xad\x7e\x1a\x42\xa9\x9c\xe8\xa7\xc5\x15\x78\xd3\x3f\x9b\xbf\x78\xd4\x3d\x7b\x3a\x7f\xe1\x58\xe3\x62\x55\x2e\xee\x44\x97\xa8\xea\x79\xf3\x07\x14\x2e\x5a\x78\xc6\x71\xcd\x5b\xe4\x51\x91\xae\xa8\x14\x32\x39\x6d\x65\xaa\x46\x88\xe7\xd2\x68\xd1\x68\x30\xbc\xe3\x67\x66\xfb\x71\x87\x83\x11\x12\xd5\x46\x27\x32\x32\x52\xf3\xb1\x77\x38\x2b\xa0\xdb\x53\xce\x65\xca\x05\x9b\xf7\xa4\x8b\xf9\xae\xab\x4d\xd5\x8f\x48\x87\xf9\x48\xae\x24\xa8\x7a\xbe\xe1\x12\x6d\x01\x1b\x18\x0b\x71\x63\x6a\x86\xce\x4d\x23\xa7\x7d\x4e\xea\xcd\x4f\x29\x91\xd0\x8e\x4e\x21\x9e\x13\x0d\x93\xd8\x71\xce\x07\x2f\x29\x08\x79\x97\xed\x6a\x45\x6b\x59\x18\x31\xbd\xae\x70\x48\x70\xbf\x46\xf2\x01\x94\x61\x5e\xe5\xdc\xf4\x3b\x87\xf1\xef\x49\x28\xbe\x75\xd5\x98\x73\xf3\x80\x2a\x96\xc9\xf2\xc9\xc5\x23\xce\x56\x97\xa2\x5e\x01\x03\x0c\xc7\x0b\x4d\xca\x81\x5f\x3d\xd2\x30\xee\x28\x07\x0b\x32\xdf\xf5\x7d\xc3\x32\xf7\x9a\xa9\x46\xea\xd8\xa8\xcf\x00\x08\x35\xc2\xb7\x87\x05\x09\xf1\x24\x6b\x53\x9a\x0c\x9c\x79\x2b\x9c\x6a\x2b\x83\xd9\xe9\x51\xe7\xc0\x0a\x51\xd7\xf3\xfa\x60\xa4\x4c\x04\xc1\xa3\xe0\x0e\xfb\xe9\xb1\x7c\xd7\x96\xdf\xfb\xd1\xb8\x3d\x83\x1a\x36\x22\xa9\x1e\xec\xa7\xf7\x28\x05\x95\xb8\x5d\x67\x27\x97\x1a\x59\x3c\x7d\xb4\x31\x7a\x51\xce\x3b\x83\x18\x2c\x89\x8d\x05\x10\x4d\xb3\x40\xed\xd9\xa0\x2f\xaf\xee\x8c\x31\xd8\xc7\x43\xf6\x07\x50\xdf\x34\x59\xb7\x12\xd5\xd2\x86\x97\xae\xcb\x7a\x19\x99\x09\x60\x83\x05\xd1\xfd\x57\x3e\xe6\x48\x80\xcf\xd7\x9f\x92\x03\xec\x51\x7f\x25\x0e\x5f\xc3\x5e\xd7\x24\x54\x20\xca\xc8\x05\x12\x04\xca\x9a\xd1\xa7\x84\x8f\xc0\xcb\x81\x58\xc7\x47\x84\xe6\x05\xf2\x05\x8a\x7e\x8b\xa4\x35\x5b\xc2\xe4\xdd\x84\x08\xf8\xbe\xf4\x76\x49\xa4\xdc\x14\x49\x89\xbe\x31\x55\x87\xf4\xe9\xbb\x52\x1b\x7f\x4d\x6a\x73\xf7\x01\x6a\xaf\xe8\xb0\xac\xf0\xbe\xcb\x0f\x2c\x74\x49\xb6\xfe\x40\xc1\x4d\x99\x6f\x74\x94\x9c\x94\x26\x4e\xe9\x38\xd3\x4c\x4e\xd2\x29\x17\x58\x35\x12\x88\x1f\x36\x05\x91\x45\xf4\xd8\x77\xe2\x7f\xa9\x46\xcf\xbf\x8d\x4c\x31\x7f\x4b\xf2\xf5\x76\x95\xe3\xfc\x0f\xc0\x60\x75\x20\x20\x2c\x7c\x0a\x10\xd0\xc2\x6e\x53\xb6\xd5\x82\x93\x5c\xe1\xbb\x27\xd9\xf7\x30\x38\xd1\x46\x21\x41\x30\x6e\xac\xa0\x4d\xf2\x4f\x35\xc8\x69\x16\x12\xc3\x76\xbb\xea\x1f\x36\x8b\xa8\x39\xce\x27\x9e\x43\x10\x10\xc9\x3c\x94\x03\xc2\xc1\xc8\xe2\x59\x9f\x32\x5f\xe8\x59\x04\x8c\x9a\xde\xe4\x7f\x7c\xae\xe2\xa6\x99\xa8\x27\xac\xc0\x57\xb2\x0d\xaf\x53\x8c\xd9\x01\xc1\xb3\x7d\xe3\x28\x34\x2d\x3d\x83\xd4\x77\x74\xaa\xd5\x0e\xec\x83\xfc\x4e\xf1\xfb\x67\x33\x81\xd3\x11\xa2\x02\x74\xea\x8c\xe1\x74\x38\x17\xcc\x37\x21\x08\xcf\xfc\x76\x0b\x85\x63\x47\xce\x2c\x46\x9a\xca\xef\x18\x07\x49\x94\xa2\x27\x10\x49\xcd\xbc\xdd\x3e\xe3\x33\x32\x63\xa1\xb3\x0e\x45\x4b\x77\x7a\xda\xf9\x02\x08\xb1\xfb\x66\xe3\x7a\x83\x0d\x77\xb4\x3a\x89\x02\x13\xb5\xaf\xc6\x86\xbc\x23\xf5\x7b\xda\x32\x13\x0d\xb8\x9d\x74\xb4\xa2\x2c\x26\x2a\xd1\xcc\x8b\x11\x2f\x18\x57\x64\x30\x52\x7b\xd6\xeb\x72\xc9\xa6\x26\xeb\x38\xea\x4d\x49\x88\x0e\x03\x01\x0b\x09\xc8\x63\xd8\x2d\x56\xb8\xae\xa1\x10\xef\xd6\x28\x56\x9f\x68\xd4\x24\x8e\x53\x92\x6b\x06\x4a\x94\x0e\x43\x4f\xf2\x0d\xeb\x0b\xdd\x8e\x59\x33\xeb\x16\x22\x9d\xc4\xab\xc1\x07\x2f\x9a\x2a\xd1\xc5\xf1\xe6\x89\x16\x59\xe1\xfa\x5c\xfb\x00\xfb\xca\xa6\x43\x75\x7b\xdc\xb0\x36\xee\x80\x8e\x35\xeb\x14\xc2\xf2\x8f\x0a\x66\xbb\x57\x15\x9b\x83\xa0\x12\x3a\x4d\x18\x65\xb3\x64\x4d\xcc\x80\x55\x0f\x99\x95\xc8\xb1\xcd\x3d\x6b\x6e\xdc\x1f\x97\x4a\x3d\x31\xe3\xe9\xa4\x78\x9d\x55\xb9\x24\x65\xae\xd9\x97\xc5\x09\x1d\xf1\x5c\x83\xc6\x09\xb6\x91\xaf\xf7\xf9\xa1\x83\x8d\xc4\x38\x0e\x9b\x2c\xa5\x3a\xb3\x13\x12\x00\x96\x18\x55\x68\x9f\xa6\x1d\x67\x98\xe8\x88\x77\xf2\xe1\xe1\x8e\xe9\x3d\xd4\x43\x70\x0b\xb5\xba\x90\xd6\xcd\xc7\x1e\x8e\x58\x3d\x6b\x58\xb5\x65\x45\x90\x65\x7c\x29\x0e\x1a\x82\xcb\x43\x39\xff\x44\xdd\x13\x16\x8f\xa8\x1b\x16\x56\x88\x1f\x0b\xae\x49\xfe\x23\xcc\x62\x48\x81\xad\x60\x47\xed\x3f\x11\xb9\xb8\x22\x1c\xb2\x9e\xe5\xd5\x67\x3e\x9b\x68\x55\xcc\xb0\x2b\xf9\x50\x7e\x93\xae\xa7\x2d\xc0\x98\x36\x67\xdb\x5f\x45\xbe\x52\x95\x99\x4b\xb1\xc5\x80\xa6\x6e\x55\x6d\xd3\x06\xc6\xc2\x10\x85\x9e\x6c\x03\x11\x93\xb0\x51\x94\x90\xbb\xd9\x6a\xda\xe6\x75\x77\x5b\xc2\x7c\xba\x49\x6f\xd9\x13\x34\xd3\xae\x59\x62\x15\xa7\xdb\x91\x9e\x45\x87\x41\xd7\xe1\x69\x81\xb5\x0b\x16\x2a\xee\x9a\x60\xee\xd1\xb3\x8e\x01\x58\xf5\x2d\x75\x36\x06\x26\xb3\x11\x0a\x20\x35\x46\x4e\x0a\x1b\xcd\x7d\x19\x22\xe2\xf6\x9f\x9d\x79\x80\x75\xb5\x10\x8b\x59\x3d\x5e\x26\xe9\x14\xd6\x0a\xf8\x98\xe6\x87\x78\xf6\x5c\xd5\x51\x00\x7b\x3c\xee\x4b\xed\x85\x37\x06\xef\x95\x41\x83\xb0\x52\x78\x5d\x21\xe9\x73\xa8\x7c\x73\x1a\xe2\x62\x15\xed\xce\x1b\x94\xa4\x52\x32\xda\xa0\xc9\x47\xee\x9a\xd4\xf8\x55\x5e\x2f\x4b\x36\x75\x51\x4b\x7c\xe4\xe1\xb7\x4a\xe8\x92\x49\x03\x5e\xb6\x92\x66\x03\xb9\x55\x59\xd0\x86\x6c\x36\x0f\xd6\xac\x6a\x33\xd8\x74\xc9\xdf\x1b\x92\x21\x60\xe9\xfd\x13\xa5\x58\xfa\xad\x93\xc8\xb7\x33\xb0\x33\x40\x3d\xa8\xfa\x03\x9c\x4e\x73\x92\x81\x45\x49\xa3\x1c\x52\x73\xc1\x1d\x60\xb9\x78\x69\x69\x5a\x8f\x9c\x99\x1e\x6f\x6d\x49\x29\x9c\x98\x91\x5e\x5a\x3a\x61\x2d\x79\x33\xc3\xe1\xc0\xc2\x34\x8c\xd3\xc1\x91\xf0\xf8\x51\xf7\x98\x17\xcc\xca\x66\x01\xfc\x36\xef\x89\x2d\xd6\xa2\xa2\x08\x87\x0a\xab\x6a\xb1\x6b\x02\x5c\x45\xc0\x66\xf0\xe8\x0a\x2a\x3e\x25\xa4\x4b\xc2\x05\x48\x53\x93\xd4\xa4\xfb\x52\x59\x4c\xa7\x32\xef\xbf\x50\x52\x2d\x22\xa9\x8b\x63\x50\x55\x15\x6e\x3c\x73\xfa\x74\xb1\x0f\xa8\x4b\xd4\x04\x14\xdb\x7f\x94\xbc\x9f\xa7\xe7\x92\x30\xa5\x77\x57\x61\x4e\x55\x91\x24\x5b\xe0\x3d\x0b\x46\x2b\x0b\xe1\x06\x2d\xff\x03\x1b\x74\x3b\x3c\xd9\x09\x0b\xd2\x0a\x08\xd7\x5c\x02\x90\x02\xd8\x87\x1a\x28\x6c\x6c\x5c\x85\x26\x57\x07\xee\x0e\xd2\x77\xb9\x1e\x83\xed\xcb\x79\xca\xe6\x4e\x22\x1c\xd2\x8b\x74\xa2\x9b\x9c\x54\xaa\xfb\x2a\x77\x96\x19\x5a\x2d\x76\xbc\xeb\x29\xfa\x92\x9d\xee\xf0\x64\x8e\x43\x30\xd8\x1f\xa1\xae\x87\xb7\x9a\x4c\x76\xdb\x82\x6d\x5a\x7e\xc2\x1f\x90\xe1\x26\x1c\x97\x07\xd6\x46\x4c\xdd\xaa\x39\x69\x46\xc0\x8b\x54\xe1\x78\x64\x87\x99\x6d\x9f\x89\xd8\x0d\xdd\x42\xc5\x10\x24\x34\xf2\x4b\x91\x2a\xad\x06\x30\x13\xde\x03\xf4\x8a\x5f\x0f\x08\xa1\xb3\x32\x5d\x35\xfb\x74\x5d\xd5\x77\x9d\xe2\xd7\xd9\x43\x4c\x4f\x4e\xcf\x91\x41\xc0\x62\xa9\x61\xb1\xaa\xaa\x77\xe5\x2f\x89\xa5\xc4\x10\x8f\xe4\x38\x4e\xa1\x94\x53\x71\xc8\x0c\xd4\x7f\x72\x86\xec\xf4\x14\xd9\x93\xb0\x5e\xcf\xd5\x2a\xf0\xe8\x32\xfb\x55\xc7\xce\x6d\xc9\x02\x36\xd8\xe1\x2b\xe5\x42\x84\x9f\xa6\xe9\xd4\xf6\xe8\xd9\x0f\xe7\xc1\x50\xa1\x50\xba\x5a\x0e\x42\x17\x53\x06\x63\x7e\x0a\x82\x62\xf5\x90\x84\x25\x1d\x0f\xf6\x76\x56\x6d\x24\xd6\xe6\x83\x96\x8a\xcb\xde\xe9\x15\x28\x9e\x91\xa6\x3c\x98\x4c\xe8\x31\xb8\x24\x5c\xca\xf4\x8d\x8f\x5a\xe1\x89\x89\x0b\x82\x10\x1c\xf6\xd1\x60\x87\x94\xa5\x0d\x98\xf1\xfb\x33\x04\x66\xe4\x13\x3a\x52\x84\x37\x3b\xd6\xd2\xac\x23\xa1\xf0\x4c\xcd\xf8\xae\x9c\x31\x1b\x94\x5f\xc2\xe5\x35\xb4\x36\x44\x9a\x92\xb6\x70\x54\x9a\x1e\x8c\x69\xb4\x77\xac\xde\x9e\xe6\x16\x4e\xc7\x08\x7e\x26\xd4\x9f\xc3\x32\x2c\x5e\xb1\x5d\x27\xf2\x24\x77\x05\x97\x9a\x34\x41\x08\x80\xc2\xd1\x79\x3d\xe3\x54\xb8\x11\x1b\xc4\x25\x42\xc8\x01\x68\x90\x50\xac\x4f\x96\xe6\xc3\x0e\x19\xdb\xb6\xa5\x45\xa7\x83\x77\x60\x89\x1a\xb1\xb4\x88\x7d\x81\x7b\x35\x70\xc8\x7a\xae\x45\x1a\xa4\xb6\xc5\xfc\x1f\x29\xcb\xf1\xd6\xcb\x92\xad\x5b\xd6\xa9\x32\x6b\x57\x2a\x2c\x3b\xa1\x31\x60\x0f\x94\xce\x3c\x51\x00\x13\xf1\x10\x01\x16\x82\x98\x25\xd4\xb2\xb3\xc8\xce\x0b\x8b\xed\x7f\x98\x6d\x37\xea\xd0\xd9\x76\xfd\x50\x07\x64\xc3\x63\x1c\x9c\x38\x23\x02\xa2\x02\x9c\xbf\xba\xf4\xc1\xa9\xaa\x8b\xef\x0e\x57\xee\x46\x64\x7a\x46\x13\x65\xe1\x08\x56\x22\x00\x87\x65\x01\x0f\x41\x17\x08\xdc\x11\x01\xbf\x1b\x99\x21\x63\xfe\x7a\x0a\x0d\x86\xb0\x22\xb0\x2c\x0f\xf0\x81\x26\xd2\x9f\x6a\x44\x1b\x46\x84\xb8\x5d\x5d\x1c\xca\x41\x3c\x8e\x5e\x24\x3a\x51\xb5\x61\x55\x2d\x57\x34\xaf\x6a\xc3\x2e\x47\x70\x6d\xf3\x6b\x79\xad\x8e\x7f\xd1\xc6\x6b\x96\x35\xdb\x70\xb8\x87\x19\x26\xe3\xb8\xed\xb3\xae\x6f\x9b\x7a\xf9\xe2\xbc\x61\x75\x8b\x2d\x21\x7c\x54\xfc\xf2\xec\xa9\xe6\x13\xcb\xe0\x35\xe4\x78\xc7\x57\x55\xff\x7a\x37\x7f\xdc\xa5\x4b\x92\x0d\x70\x80\x3c\xcb\xd3\x55\x5b\xde\x3e\xff\xf6\x51\xf7\xed\x0b\xf5\x33\x4b\x54\xd0\xbe\x76\x68\x79\xf6\x34\x7f\xc1\xd2\x73\xd7\xac\x49\xa8\x8d\xab\x34\x9b\x8d\xac\x2f\xb1\xbf\x8d\x40\x62\xfc\x70\x4d\x97\x35\x30\x57\xb6\x8a\x1f\x6a\x70\xe6\x68\xdd\xaf\x8f\x2e\x9b\x89\x49\x91\x7d\x41\x05\x15\x06\x86\xc7\xad\xee\x03\xa6\xc9\xb6\x85\xd4\x55\xc3\x01\x3b\xae\x86\x85\x64\x73\x8d\x37\x6d\x98\x71\x02\x12\x34\xda\xb0\xfa\x54\x95\x46\x22\x92\x06\xe7\x59\x9f\x72\x70\x52\xca\x48\x2b\xa0\x5f\xe6\xa9\x66\xca\x84\xc0\xe8\x8d\x20\x4c\xb0\x11\x0d\x7f\x63\x0c\x40\x66\x1f\x6c\x7f\xc8\x2f\xa7\xa8\x40\xf2\x0b\xb4\x6e\x9d\xcb\x5b\xd5\xb1\x51\x40\x07\x55\x20\x4f\x5f\x36\xea\x93\x48\x2d\x13\xa3\x26\x01\xba\x2f\x23\x72\xe7\xee\xe8\x1f\x5a\x21\xda\x84\xda\xfe\xdf\xd2\x82\x54\x70\xbf\x9d\x4c\x20\xd5\xcd\x74\xea\xf7\xc2\x50\x44\x55\x6f\xde\xd1\xfd\x14\x6c\x23\x6d\xd5\x85\x69\x88\xf9\xa0\x84\x20\x38\xaf\xea\x42\xb6\x8d\x52\xbd\xc6\x3d\x38\x72\xa7\xc3\xb4\x66\x20\xd8\xf8\x38\xa1\xbf\x03\xe4\x5f\x47\xed\x07\xb4\x41\xdc\x6a\x57\x07\xdc\x42\xb6\x63\xd6\x37\x62\xeb\xd2\x49\xbe\x23\x7d\x03\x31\x4f\xa7\xd2\xe0\x0d\x17\x77\x1a\x77\xa7\x4e\x51\xab\xf2\x4a\x33\xb1\xe0\x00\x4c\x50\xd4\x39\x44\xe0\x97\x57\x3d\xad\x15\xf5\x57\x6b\x34\x13\xd6\x80\xb6\x9e\xf1\x87\x95\xf8\xaf\xd3\xd3\x77\x6f\x66\x89\xeb\xcf\xda\xfc\x2d\x27\x99\x49\x46\xb0\x77\x5a\x2f\x93\xd2\x90\xbf\x38\x6f\x89\x54\x37\x23\x1b\x6a\x82\x9c\xdd\x9c\x46\xf3\x91\xb9\xc4\xe5\x82\xe2\xb2\x0b\x2c\x01\xd2\x1b\x46\x32\xe4\xcc\x6e\xa6\xdf\x10\x62\x9d\x3d\x8a\x4f\x84\xed\x81\x79\x5d\x10\xa9\x92\x0b\x82\xf6\xe0\x56\x83\x10\x19\x82\x84\x36\x9c\xb2\x7c\xdb\xba\xbd\x62\x03\xd6\xdd\x12\xe6\x06\x94\x00\x32\xdc\xda\x7a\x46\xe3\xf5\x07\x5d\x38\x68\x51\xd2\x07\xfb\x33\x15\x36\x2a\xfe\x57\x1e\x97\x48\x66\x8a\xe3\x50\x35\xa3\x36\xf7\xe5\x9a\x23\xe9\x74\x40\xde\x09\xa9\x8a\x58\xe4\x82\x54\x20\xe7\x7c\xe4\xc8\x45\x27\x49\xc8\xda\x86\xd6\x11\x6b\x8c\x20\x88\x80\xe1\x75\x14\x0d\xca\xd8\xfd\xd9\xe9\xe5\xe5\xd5\x8d\xe7\xf2\x4c\x59\x75\x41\x67\xd1\x37\x2e\xfe\x66\x34\x2e\x8b\xc2\xc1\xf8\x10\x90\x15\x41\xf8\x38\x20\xad\x71\x0c\x2e\xdc\xf8\xd6\x3a\x25\x97\x0d\x76\x73\xc3\x63\x91\x1a\x45\x3c\xfe\xe2\x98\x82\x92\x7c\xe4\xe3\xf1\x53\x62\x36\xc6\x2b\xfe\x9f\x84\x66\xda\xc0\x34\x0e\x6a\xf6\x16\x74\x1f\x6e\x4a\x03\x68\x8a\x91\xd9\x16\x6c\x6f\x97\x43\x02\x25\xdc\x37\x60\xa4\xb7\x29\xbc\x6b\x27\x6c\x85\x6a\x5a\xd0\x20\x23\x77\x57\x57\xbf\xef\x70\xbe\xb3\xfc\x49\xf2\x0a\x87\x75\xcd\xab\xb5\x70\xdb\x3f\xbb\x1f\x92\xcf\xa9\x41\x2c\x66\xd0\x39\xfd\x7a\xd6\x6d\x39\x52\x8d\xb8\x6d\xf7\xfc\x5b\x52\x18\x48\xdf\xc2\xdf\x27\x6c\xdd\xd0\x54\x5e\x54\x3b\x3a\x48\x49\x7c\x64\xb7\x35\xad\x27\x55\x79\xc1\x96\x8a\x3b\x33\x80\x0d\xc3\xe6\x51\x66\x91\x95\x5c\x86\xf0\x4a\xe4\x4e\x0c\x4b\x85\x6d\xb1\x60\xf4\x62\xfa\x4a\x83\x69\x31\xbb\x66\x72\xbf\x2b\x43\xd4\xa9\x8b\x42\x17\xfa\x9c\xfe\xb5\x15\xc2\x43\x25\x9f\xef\x30\xa4\xc1\xfd\x05\x97\xe9\xfb\xbd\x26\x02\x58\xb0\x86\x35\x5b\x56\x3d\x09\xf9\x7c\xd7\x03\xaa\x37\xed\x20\xe2\x92\xb8\xfe\x20\x29\xcb\x99\xa8\x6b\xb0\xa8\x58\xd5\x55\x9f\xf1\xc1\xbd\x91\x90\x76\x6a\x36\x5f\x8b\x50\x14\x63\x5e\x3c\xc8\xe9\xfb\xdf\x4e\xcf\x2f\x7e\x9b\x6d\x0a\x8b\x70\x51\x7c\x6a\x68\x4b\x80\xd1\xa2\xbc\xcd\x77\x6b\xb3\xbd\x61\xc2\xc8\x48\x7f\x45\x86\xde\x86\x20\x35\x89\xf0\x77\x2f\x67\xa4\xdc\x8f\x78\x63\x39\xdf\xb1\x10\xfc\xfd\x11\x8b\xd4\xd0\xad\xf3\xf5\x86\xa9\x61\x0b\x0f\xdb\xa7\xd8\xe7\x9f\xb1\xb5\x31\xd5\xb8\x90\xc8\x1b\x9a\xe8\x6d\x0d\x8b\xca\x77\xd7\x35\x24\x2c\x3f\x2c\x3d\x4e\xdc\xa6\x2c\xe5\xc7\x69\x7c\xbe\xde\x95\x03\x22\x17\x3c\x1a\x8d\x5b\x4f\xba\x2c\x17\x7a\x89\x24\x58\x17\x85\x98\x21\x9c\x39\x33\xbd\x80\x1d\xe9\x2c\x73\xab\x2e\xe8\xa0\xcc\x33\x80\xf8\x54\x8b\x91\x7b\x23\x99\x12\xb4\x8a\x08\x39\x08\xdf\xb1\x11\xd5\xfc\xf7\x79\x18\x80\x9e\xc8\xa6\xb0\x9d\xa6\x5b\xe4\xd6\xed\x35\x84\x32\x73\x9c\x6a\xbc\xc9\x70\xdf\x25\xc0\x54\x18\x5d\xc2\xec\xad\x60\xfe\xbc\x3d\x64\x6c\xca\x01\x4b\xde\x1e\x12\xc4\x60\xd0\x81\x96\xe1\xbc\x94\x4c\x30\xc8\x75\xb5\x95\xdb\x52\x54\x50\x95\x12\x48\x89\xc4\xd5\xbf\x24\x82\x14\xb7\x42\x58\x68\x5c\xa1\xe2\x02\x62\xc4\xbf\x80\x5f\xf5\x2c\xaf\x8b\x69\xf9\xf9\xb7\xd9\x9c\xf6\xe8\xdd\xb7\x81\xfc\xce\x97\xad\x58\x68\xff\x86\x24\xab\xbd\x3a\x40\x3f\x48\x2a\xb1\xdf\x7f\xc1\xaf\x1d\x07\xe6\x89\xb7\x95\x13\x89\xfe\x62\x0b\x6d\xa2\x77\x7c\x98\x19\x25\x2c\xa1\x2a\xdb\x20\xe9\x34\xe4\x1c\xbf\xef\x78\x96\xa2\x7a\x3c\x4f\xff\x95\x7f\xa5\xaf\xf8\x97\x4e\x85\xb7\xb1\xdb\xa3\x58\xe1\xc1\xc6\x0e\x23\xd5\xc0\x71\x34\xdc\xd3\xef\x69\x09\x6f\x09\xb0\xaf\x71\x2d\x06\xc8\x31\xd1\xc9\x76\xc7\x3e\x7c\x5e\x77\xeb\xed\x1d\xe5\x20\xc0\x9c\x33\xf9\x0c\x0b\x5a\x70\xe6\xfb\xa8\x8d\xc4\xb1\x0a\x65\x11\x7d\x5b\x42\xde\xa2\x7f\x5a\x96\x11\x70\xd6\xe7\x30\xd8\x0a\x10\x91\xdc\x7f\x4e\x6f\x28\x47\x21\xca\xb0\x28\x51\x50\x94\x0f\x6f\x15\x61\x1b\x75\xe0\xb8\x9c\x20\x92\x5f\x97\x5d\x4f\x28\x82\xf2\xeb\x7e\x24\x3c\xc6\xaa\x97\x50\x42\xa4\x12\x0d\x74\x15\xa3\xbc\x24\x13\x98\x3c\xdb\x9c\xc3\xc6\xde\xe7\x7b\xf9\x49\x98\xd6\x6b\x48\xaf\x25\x25\xd9\x08\x84\x16\x50\x84\x4b\x3b\x78\x9c\xeb\x4a\xc3\xef\x2c\x9d\xd8\x00\x66\xe3\x81\x58\xc9\xe0\x16\x54\xba\x18\x94\xdf\x8a\xbc\xff\x92\xa5\x7d\xcb\xcb\xc1\xbf\x52\x0b\xeb\x70\xf9\x1b\xda\xfe\x62\xdd\xbb\x90\x94\x2b\x29\x24\xe2\xe8\x9c\x2f\xdc\x59\x9e\xc5\x74\x5e\xf1\x7f\x97\x4b\x04\xa3\xfb\x87\xfe\x27\x8a\x79\xce\x55\xcd\x4e\xae\x5d\xf9\xec\x4c\x78\x9c\x14\x62\x39\x46\x85\xd9\x76\x9d\x2f\x4a\x17\x43\x0a\x20\xf0\x6d\xbe\xf2\xa5\xc0\x24\xfa\xb1\xe3\x7d\x4e\xe5\x8f\x68\x3b\xd3\x2f\x2b\xa1\xcd\x40\x67\xa1\x2b\x3a\xe3\x9f\x85\x15\x12\xee\x39\x2a\xd1\xc6\x10\xf5\x1f\x96\xd1\xf9\xc1\xbc\x49\x4c\x7a\x97\x2c\x5d\x73\xda\xa4\x8e\x41\x0d\x47\x4d\x21\x31\x1d\x83\x39\xda\xf2\xe6\x48\x4d\x3a\x18\x38\x76\x1e\x72\xa5\x26\x07\x10\x7a\x10\xe1\xf8\x19\x97\xcc\x38\x1c\xd8\x6d\x88\x53\x38\xe1\xb0\x29\xa6\x40\xa5\x03\x8e\x9f\xe2\xc0\x40\xdf\x65\xa1\x7a\xd2\x54\x25\xe1\x2a\x45\x36\x3f\x68\x1d\x61\x26\x05\xbb\xf8\x8e\x54\xd9\xb0\x1f\x0f\x5c\x56\xab\x5c\xb8\x8c\xb0\x0a\x2f\x32\x1a\x26\x08\x49\xa7\x8f\x3e\xfe\xf0\xa9\xe3\x96\x9d\x19\xe5\xe9\xa3\x8f\x3f\x7e\x22\x56\x8c\x7f\xcc\x8b\xad\xf6\xb6\x2d\xef\xab\x66\x87\x3b\x87\x9a\xf4\xa4\x86\xc8\xe3\x4b\x8e\x32\xd6\x2c\x59\x76\x93\xe0\x3d\xcd\xc5\xe5\x8b\x66\xdd\x78\x9a\xc4\xaf\x21\x80\xa8\x0a\x8f\x94\x54\xba\xb8\x18\x64\xeb\x16\xe3\x11\x5c\x38\xf5\x60\x41\x04\xb2\x2c\x2a\x6e\xe7\x37\xfa\x17\x17\x0c\xdc\x55\x71\xa1\x8b\x54\x93\x01\x22\x5e\xcd\x2e\xcc\x8c\x5b\x51\xa7\x0f\x40\x9d\xae\x32\x09\xe6\x25\x59\x35\x50\xd2\xc1\x22\x9b\x08\x92\x8c\xfa\x6b\x99\x63\x55\xb5\xdc\x1a\xe2\xb6\xd9\x8a\x87\x52\xf1\x67\x69\xcb\xc7\xfd\x2c\xd3\x5d\x7b\x15\x55\x46\xea\x23\x85\x55\x47\x8a\x0d\x44\x01\x73\x0f\xd8\x90\xdf\x97\x41\xf1\x04\x13\x09\x4a\xa7\x19\xc9\x10\xa0\x90\xd3\x96\x13\x8f\xba\xa8\x6f\x3a\xc7\x77\x65\xa6\x9c\x94\x76\x3a\xfd\x4a\xf1\x6b\x38\x04\xe6\xa9\x53\x7d\x5b\xcb\x83\x19\x11\x42\xe6\x2b\x92\x87\x24\x26\x52\x0e\xee\xe0\x40\x23\x8c\xaa\xb7\x5f\x55\x61\xc5\x6a\xd4\xbc\xd4\x72\xd5\x27\xb1\x63\x7b\x01\xe1\x86\x61\xc1\x84\x56\x13\x96\xfa\x49\x9f\xd3\x8c\xf9\x08\x49\xbf\xb3\xcb\x72\xdf\xc7\x93\x2c\xc5\x61\xc5\xff\xc3\x02\x77\xcb\x43\x9b\xca\x84\xa4\xb4\x45\x34\xae\x39\xfe\xf6\xc3\x89\x0b\xd6\x7b\x7c\xa0\xe6\x9e\x6c\x36\x4f\x8a\xe2\xf1\xc4\xac\x03\x7a\x72\xd3\x1e\xd8\x1d\x95\xa3\x0d\x08\x2b\x68\x29\xd8\x9c\xd3\xb8\x63\x80\x68\x9d\x3e\x70\xc8\x43\xc9\x5a\x47\x5a\x78\xbc\xc1\x4f\x12\xac\x5d\xd7\x90\xc2\xdf\x6c\x09\xed\xce\xbe\xc3\xc6\x08\x09\x02\x0b\x67\x32\x70\x3e\x06\x45\x83\x58\xd5\x07\x87\x67\x78\x10\xa7\x58\xc7\xba\xec\xe6\x08\x4a\xe4\x9e\xe9\x51\x84\x04\xec\xc4\x23\xd5\xb1\x94\x09\xc0\x29\x86\xe2\xfb\xfe\xf7\x64\x2a\x53\x9d\x4f\x91\xc0\xe7\xd8\xca\xd4\x95\x77\xcb\x9b\x09\x7d\x23\xb6\x40\x52\xbe\x28\xb8\xaa\x02\xfc\x9c\x85\xbf\x3d\xd8\xaa\x69\xee\xe4\xba\xce\x1c\x49\x5f\x42\xfa\xbf\x15\xf2\x6d\xe0\xd7\x71\xe9\x3c\xef\xaa\x45\x78\x57\xff\x57\xce\x98\x18\x62\xc1\x6b\xdc\x66\xff\x10\x39\xe5\x1c\xbf\xd2\xff\xc5\x84\xe1\x40\x34\x30\xe0\xca\xae\x67\x5d\x73\x78\x80\x2b\x55\xc7\x6c\xd0\x95\xfa\x91\xc7\x7d\xa9\x8f\x93\xd5\x80\x69\xfb\x93\x73\xf0\x1f\xab\x62\xf4\x31\xd4\xdc\xd9\x74\xea\x1c\xa1\x23\x5f\xff\x94\x8f\x3f\x0e\x45\x7c\x80\x50\xdc\x50\x5c\x94\x13\xeb\x23\x9a\xbc\xb2\x40\xa9\x31\x98\x33\xe7\xf9\xe0\xa8\x58\xd9\x67\x63\x75\x2d\xbe\x4f\x04\x48\x71\x20\x15\x67\xc5\x51\x59\x44\xd7\x72\xb7\xd9\xdf\x6b\x40\x90\x35\x6c\xbf\x7c\xad\xc3\xfa\xc5\xb3\x0f\x08\x91\xe4\x68\xb3\x4e\x8c\x25\x1a\xea\x25\x6e\x7f\x31\x03\xe6\xee\x5a\x10\xfb\x16\x86\xf6\x1d\xe7\xd1\xf1\x77\x7b\x24\x6e\xc0\x86\x8a\xb2\x80\x7c\x06\x51\x32\xc0\x7d\x60\x6b\x18\x00\x1a\x52\xae\x88\x3f\x89\x6f\x42\xaa\xe5\x51\x94\x99\x04\x34\xc2\x00\xa3\xd6\xcf\x79\xbe\xb8\x73\x23\x62\xf6\x57\xb6\x3d\xe2\xbb\xc6\x68\x67\xff\xf2\x02\x72\xd4\xb3\xed\x8b\x27\xb0\x21\xc8\x55\x70\xcc\x42\x36\x78\x75\x1b\x20\x04\x3e\x16\xf6\x99\xdc\x57\xc5\x8e\xc8\x9b\x17\x63\xf6\xec\xe9\xf6\x45\x5c\x9f\x28\x02\x76\xa5\xa3\x6d\x0c\x16\x8e\x95\xda\x0a\xf7\x4a\x38\x80\x12\x91\x7c\xb7\x3e\x40\xb5\x43\x0f\x47\x77\x51\xc0\x8a\x02\x52\x37\x76\xf2\x99\xf8\x86\x31\x4e\xcc\x00\x8c\x07\x41\x60\x04\x76\x30\xec\x12\xcd\x02\xd2\x86\xa3\xc1\x68\x76\xa2\x29\x71\x60\x0c\xac\x67\x3e\x5e\xd0\x0d\xcd\x2a\xb4\xc7\x87\x17\x1b\xd4\xd3\x09\x43\xba\x03\x65\x57\x9e\xe7\x98\xa2\xb4\x16\x05\xe6\x73\x16\x64\x1f\xaf\x30\x70\x2c\x46\x6d\xc5\x8e\xc5\x60\x80\x72\xd4\x1c\x6b\xe7\x6c\xb2\x0d\x75\x7f\x04\xad\x20\x2c\xb8\x42\x00\x68\xa6\x77\xd5\x24\xa4\x29\x1d\x46\x60\x6a\xe9\x7e\xd5\x04\x37\x25\xc4\xdb\x89\xcd\x1a\x0e\x64\x16\xcf\x75\x2f\xe7\x83\xe2\x45\x4f\x8b\xc1\x31\x62\x9b\xcf\xce\x12\x44\xdd\x6f\x76\xc4\x5b\xd6\x15\x2d\x3a\x8e\x0c\x7d\x71\xe1\xea\xfa\x06\x77\xd9\x89\x17\x12\xa3\x59\x32\xbd\xa6\x7f\x59\x91\xaa\xc5\x71\xb1\xfc\xf0\x01\x87\x2b\x2c\xd3\x66\xb1\xe0\x20\x85\xaa\xd6\xbb\xa2\xfb\xd2\xdc\x69\x75\xb1\x96\x80\x85\x30\xdc\xc3\xf8\xae\x18\xce\x52\x3c\x6e\xc0\x4c\xa0\xdb\x96\x0b\x12\x4a\x66\xe9\x5b\x12\xd1\xf8\xc6\xbc\xbc\xa9\x00\x86\xf9\xa0\x9d\xcd\xcd\x04\x06\x2f\xd6\xf2\x66\xe3\x03\xd2\x3d\xbd\x62\xa7\x24\xe6\xbd\xe5\xa0\x48\xd1\x46\xb9\x80\xc4\x89\x72\x7d\x2b\x01\xae\xec\x51\x84\x28\x27\xf7\xf4\xd9\xab\x21\xd7\x97\xd9\x14\x88\x06\x34\x54\x03\x8e\x59\xdc\xea\xe2\x99\x6d\xcb\x96\xc5\x11\x0b\x6a\x0a\xe3\x59\x86\x63\x82\x1a\x67\xe3\x7a\x23\x6c\x01\xcb\x07\xc1\x55\xae\xe0\x9d\x30\x2f\x66\x99\xcf\x9c\xe5\x66\x1c\xde\xca\xb5\x3b\x3e\xe9\x08\x5f\x88\x19\x37\x10\x39\x3f\x70\xb7\x86\x83\xa7\x77\xba\x1c\x16\x2a\x06\x84\x72\x3f\x13\x23\xd2\x03\x99\x11\x24\xae\xa0\x11\x84\x77\xda\x03\xc8\x3c\xf7\x43\x16\xa6\xe0\x5e\x0e\x78\x1d\x51\xa2\xee\x29\xb4\x18\xde\x46\x16\xf2\x7d\x60\x1b\x05\x54\x1e\x3d\xa6\x83\x19\xea\x2d\xbc\x67\x7c\x85\xec\x05\x53\xef\xb3\xa7\x48\xda\xcd\x43\xa3\x3c\x7e\xbb\x23\xa0\x38\x7e\x97\xa1\x21\xfc\xe1\xe8\x6b\xcb\x65\xde\x16\x16\x82\xaf\xd4\xcf\x1e\x66\x50\x79\x18\x61\x95\xaf\x49\x22\xd7\x26\x68\xb7\x12\xc8\x1d\x9b\xd7\x88\x50\xf8\xe5\x19\x53\x42\x98\xf3\x17\xb2\xb5\x38\x78\x85\x08\x7e\xb7\xe5\x3d\x20\x1b\xca\xfa\xc1\xb4\xbf\xfb\xd3\xf5\xd5\xe5\x49\xfa\xc7\x93\xfd\x7e\xff\x84\xab\x3f\xd9\xb5\x6b\x0e\xf3\x28\x38\xc4\xff\x7f\x5e\xbc\x3d\x49\xcb\x7e\xf1\xfd\x8c\xa4\x77\x6c\x0d\x2f\xf6\xaa\xf7\xfb\x96\xbd\xf2\x4c\x96\xac\xd9\xfd\xf3\x5b\x66\x2b\x77\xc1\xf4\x9d\x94\xf0\x66\x58\xc8\xb4\x79\xd9\xcd\xba\xa4\x54\x20\x56\x26\x2f\x31\x96\xa4\x2b\xe1\x2e\x28\x12\xbe\x00\x58\xb5\xe5\xfb\xc0\xe8\x10\xe1\x06\xf9\x1d\x7b\x0f\x77\xeb\x42\xe8\xd4\x38\x1a\xcd\x4e\x51\x56\x16\xbf\x0c\x5b\x82\xd1\x19\xcf\x42\x3c\x4f\xff\xc4\x8a\x1e\xa3\x54\xa8\x80\x8b\x8c\x0a\x00\x1c\xd2\x12\x76\x58\xaa\xf7\x5a\xcb\x61\x81\x37\xff\x9f\x97\x3d\x02\xe1\xa6\x68\x43\x46\xee\xc6\xe6\x57\xd3\x36\x2a\x9d\x6b\xd4\x58\x2b\xdc\x5b\x9c\xda\x11\x35\x0f\xf6\x00\x9f\x4b\xfb\xe1\x3e\x18\x1e\x49\xba\xc9\x3c\xbb\xd7\x4d\x36\xe2\xf8\x0a\xf8\xb9\x7d\xa6\x12\xc4\x48\xa2\x0b\x7a\x50\xc9\x6e\xd4\x83\x84\xc8\x64\x3a\x4b\x8b\x50\x47\xd8\xcc\xb9\xcb\x8b\x8f\x20\xa3\x1a\x30\x90\x98\x64\x18\x21\xdd\x9a\xc4\xbc\x2c\xdc\xe1\x7c\x98\x45\x91\x51\xd7\x0c\x82\x78\x28\x76\x1b\x9a\x8b\x6d\x14\x0d\x16\x8a\x19\xd2\xaa\x45\x3b\x48\x54\xc6\xa0\x70\xf8\x5e\xd1\xa0\x98\x35\x0b\x79\x10\xed\x4c\x52\x21\xb6\xb6\xeb\xe6\x60\x01\x73\xe7\xf8\xa5\x91\xe8\xe1\xcc\x3c\x98\x4e\xca\x43\x06\x12\x7c\x93\xc5\xcd\xfd\x35\xb8\x93\xac\x62\x40\x7d\x48\x05\x86\xbd\xe9\xa1\xa8\x17\x59\x65\x26\x86\x37\x11\x73\xe5\xa0\x86\xd1\x61\xe7\xae\x87\x23\xd1\x61\x71\xd5\x30\x42\x2c\xa8\xfa\x05\x11\x62\x31\x92\xc6\xf1\x5f\x7e\xaa\x5f\x10\x02\x36\x35\xe9\xc0\x00\xa1\x64\x3c\x85\xf8\x89\x0a\x53\x86\x88\x22\x9c\x9b\xb7\x44\x84\x66\x07\xd1\x0d\x68\x2b\xdc\x36\x23\x85\xef\x4b\x74\xcc\xa9\x91\x78\x94\x04\xc8\xfd\x9c\x59\xa2\xa8\x6e\x6f\x67\xf3\xb6\xd9\x77\x1c\x82\x86\x57\x87\xd8\x29\xc6\xbf\xd3\x6b\xfc\x16\x90\x6d\xde\x0a\x51\x48\x42\x32\xc5\x89\x43\x99\x92\x90\x4c\x3e\xda\x46\xaf\xbe\x9c\x53\x09\x1e\x5a\xe1\x47\x98\x38\x72\x5c\x4a\x66\x52\x85\xd8\xf9\x3e\xe3\x14\x42\xe7\x60\x22\x61\x55\x1c\x95\xae\x39\x47\xc1\x38\x69\x08\xb7\x40\x1c\xb6\xad\x5a\x2c\x3f\xe4\x30\x1f\x93\x03\xc2\x32\x38\x02\x23\x62\xa8\x20\x68\x79\x90\x30\xa4\x87\x20\x0c\x97\x1e\x42\x11\x84\x4d\xff\xeb\x9b\x4b\xf9\x09\xb7\x9c\xde\x6c\x80\x5f\xee\x25\x07\x48\x98\xb3\x6f\x36\xe5\xf4\xb3\x32\x71\x9e\x8a\x7e\x6a\x8f\x39\xe2\x97\x83\x28\xda\xfc\x16\xb6\x4a\xfe\xef\x72\x49\x98\xf3\xd5\xde\xb5\xe5\x93\x61\x35\x42\x8e\xa0\xfa\x1a\x09\x97\xaf\xb6\x46\xfe\xe7\xf2\x72\xb6\x2b\x06\x38\x7c\x54\x78\x8c\x98\xeb\x90\xe8\xee\x11\x1d\xb4\x15\x2b\xe0\x4a\xa0\x83\x0e\x41\x1d\xfe\xb2\x3e\x68\x07\x0f\x23\x1a\x44\x9f\x2f\x5d\x20\x5c\xbe\x14\x77\x88\x2f\x83\x68\x6f\xb7\xab\xa2\x3a\xfe\xc6\xbe\x99\x14\xbc\x6b\x98\xca\xf1\xf4\xd8\x22\xf4\x38\x53\x26\xbb\x9a\x71\x41\xa6\x5b\xcd\x86\x0b\xe1\xdc\x32\x8a\xb3\x14\xbf\x1d\x94\x49\x2a\x4c\x2e\xd9\xa6\x08\x84\x15\x21\xa0\xf0\x58\xb9\xc8\xdb\x3b\x7e\x8b\x08\x8e\x22\x6b\x60\xdf\xea\x8d\x18\xfe\x1f\xae\x98\xbe\x81\xf5\x4e\x52\xa3\x0e\x63\x3f\x25\x6a\x43\x67\x32\x66\xea\x2a\xb0\x74\x25\xb7\xaf\xde\x4a\x4a\x1e\xaf\x1c\x52\xc6\x38\x22\x94\xca\x9e\x0c\xd7\x2d\x80\x77\x88\xfe\x4b\xf9\x7f\xff\xf7\xff\x21\xf6\xb4\x6d\xe8\xb4\x44\xac\xb2\x5e\x93\xf5\xeb\x6e\x71\x2e\xfe\xc5\xb2\x27\xe0\xd1\xc1\x40\x04\xfd\xa9\x86\xff\x52\x6a\x44\xa3\xfc\x9c\x91\xd1\xf7\x35\xdb\xa8\x62\x22\x87\xb6\xe3\xc9\x1c\xf6\xf1\x61\x1b\x46\x54\x99\x9e\x11\xee\x9a\x9e\x2d\x2e\x16\x4d\x2e\xbf\x28\xd1\x4d\x1f\x29\xc9\x47\xd2\xa9\x3f\xf9\xcb\xdc\x6e\x21\xa2\x8b\xdc\x50\x71\x3c\x8c\x21\xec\x15\x93\xdf\xf8\xed\x46\x51\x19\xe5\xe5\x08\x66\x2d\x2e\xbc\x4d\x2e\x57\x4a\xe8\xbd\x6b\x24\xec\xe8\x71\x67\xf1\xf7\xfa\xa8\x08\x22\xdc\x27\x2e\x41\x84\x81\xfd\xa4\x31\xaa\x53\x42\x2e\x8d\xaa\x3b\x26\x7a\xca\x15\x91\x1a\x66\xff\x31\x31\xb0\x48\xd4\x4f\xc0\xd1\x03\x9c\xe0\x7b\xbd\xfc\x40\x26\x93\x9f\x58\x78\xdf\x20\x83\xf6\x35\x32\x70\x67\x1d\xf1\x11\xfc\x3f\xc1\x4d\x41\x35\x52\x70\xae\xa6\x34\x7f\x70\x1b\xb1\x8d\x5e\x5e\xf2\x31\x24\xb8\xa5\x1c\x3d\x75\xc4\x8d\x03\x51\x13\x2e\xa2\xd1\xdd\x75\xac\x0c\x72\x1f\x82\x8e\x22\xf1\x1e\xaf\x61\xb5\xd3\xab\x2e\xdc\x16\x71\x39\x75\x26\x2b\xc9\xe0\xe6\x34\x3f\x31\x52\xf3\xa3\x61\x86\x65\xd7\x4d\xb0\x65\x56\xe2\x3f\xf2\xd5\x78\xbd\xf2\x39\x6d\x9e\x5f\x04\x9e\x63\x34\xaa\xae\x0b\x84\x04\xd4\xf1\xd9\xe9\x9a\x14\x84\x75\xa4\xcc\xa0\x21\x16\xe5\x7e\x39\x12\xcc\x36\x7e\x65\xe0\xeb\xc3\xd9\xc6\x6d\x3c\x1c\xd0\xf6\xcf\xba\x2e\xa6\x6f\x10\xba\xe2\xf1\x55\x42\x57\x34\x75\xa7\xf0\xdf\xe0\x48\x20\x92\xd2\x61\x8c\xf6\xf6\x51\x4f\x82\xd6\x71\x86\xe8\xe3\xaf\x3b\x7c\xbd\x3f\x21\xba\x53\xff\x05\xd2\x5e\x3c\xe3\x40\xd0\x8b\x46\xe5\x10\xc2\x06\xab\x38\xd6\xfa\x98\xf6\xe6\x05\xd7\x88\x67\x0c\x75\xbc\x51\x68\x35\x66\xfa\x60\x95\x38\xd0\x3a\x1c\xa6\x33\x4f\xf9\xd0\x64\xb3\xe2\x48\x88\xb5\x98\xf3\x3e\x1f\x67\x7d\xc4\x3e\xfc\x50\xc0\xf5\x70\x94\xcc\x6b\xdc\xfb\xab\xe1\x20\x1f\xac\x11\x1e\xb3\xb1\x0f\xe6\xdf\x12\x84\x3d\x6d\x83\x65\x1d\x70\x6f\xa6\x18\x1c\xca\x86\x3f\x6f\x50\x60\x1d\xc2\xf0\x25\x4a\x86\x67\xb8\x1e\x73\x3b\x3c\xab\xda\x0f\x07\xcd\x57\x34\x84\x7b\xcf\xf4\x82\xb1\x5d\xdf\x19\xe4\x7b\xd6\x87\xdb\x51\x5b\x89\x98\xf6\x40\xf2\x1b\xe2\xce\x64\xc9\xb0\x7e\xdc\x47\x1c\x7a\x6e\xb9\xce\x0c\x7e\x81\x84\xcb\x27\xac\x2d\x4a\x44\x02\x9f\x49\xca\x95\xa8\xae\xa5\xef\x64\xf8\x41\xc8\x1b\x08\xcf\x61\x09\xf5\xb9\x7a\xea\x29\xae\x39\x98\x92\x16\xe5\xb0\xe5\x25\xcc\xdd\xa5\x60\x5e\x26\x01\x54\x71\x53\x47\x05\x09\xf9\xe7\x61\x5b\xf2\x1e\x9c\x9e\x9e\x97\xcd\x3e\x91\xa3\x73\xc6\xd7\xf6\x53\xb9\xb3\xaf\x39\xf1\x90\x24\x8f\x65\x14\xbd\x2b\x83\x39\x90\x98\x2e\x57\x63\xc6\xe5\x83\xe8\x60\x9c\x1c\x2e\x2e\xd8\x9e\xe0\x60\x01\x14\x52\x03\x02\x3a\x59\xae\x0f\x89\x63\xa6\xad\x42\x80\xf5\xdd\x8a\x24\x1a\xf5\x1b\x42\x7c\x49\xc7\x3c\xce\x51\x77\x27\x66\xdf\xc2\x8d\x4c\x0e\xfa\x14\x7e\xb8\xb1\x71\xc8\x93\x95\x6e\x1c\xee\x3d\x54\x3f\x8e\x10\xe2\x4b\xc6\xc1\xbd\x3c\xe5\x27\xe4\xb1\x88\x0f\x8d\x87\x94\x43\xbd\x60\x1a\x7a\x4f\xba\xe1\x10\x7d\x78\xed\x4d\x70\x5e\xc3\x03\x59\x0c\xe4\x0f\x36\x6f\x8e\x0f\x4e\x29\x11\x47\xd8\x84\x88\x20\x8e\xe2\xc9\x7b\x46\x9f\xdf\xe2\xbc\xd2\xa8\xe9\x40\x03\x17\xb0\x07\x9b\x3a\x85\x74\x5c\x5e\xa4\x83\x8c\x75\xa1\x72\x9d\x14\x7e\xfe\xe0\x15\x38\xbb\x21\x24\xf2\x5d\x78\x64\x40\xc0\xb3\x95\x2c\xe4\x3d\x22\xb7\xc7\x99\xd5\x05\xbd\x8e\x1b\x73\xac\x1a\x50\x8e\x45\x8f\xe1\x8c\x77\x86\xd2\x59\x60\x6c\x65\xa6\x7c\x62\x32\xab\x78\x5b\x0d\x6a\x93\x1f\x22\x07\x30\xdf\x8c\x62\x8d\x2c\xda\x35\xc7\x4f\xec\xf1\x50\xfc\x59\x2d\x8f\xfc\x38\x82\x39\x6a\x94\x99\x85\x5b\x7d\x4c\x20\x9e\xec\x96\x6d\xce\xb6\x70\x5b\x6b\x66\x16\x01\x29\xa0\xc1\x9f\xdd\x2c\xdd\x83\xc9\x9e\x1b\xc0\xc3\x46\x0d\x3d\x7e\x88\x29\x7c\xc5\x00\xc0\x36\x1e\x1e\x01\xd8\x82\x3c\x55\x44\xc3\x08\x58\xc0\x43\x03\xd1\x97\x8e\xbf\x7c\x20\xe0\x1b\x5f\x38\x90\x13\x1b\x85\x3e\x90\x51\x14\x93\xfb\xff\xa1\xf1\x0d\xd4\x1d\x10\x67\xf4\x02\xcb\x80\xe0\xa3\xaf\x4e\x38\xa2\x0f\x62\x21\xac\x59\x38\xc0\x34\x36\x43\x8f\x33\xdf\x54\x4d\x4b\x08\x55\xb6\xee\xc3\xf8\x8d\xf8\xea\x03\x47\x14\xf4\xed\x41\x45\x12\x9e\x5c\x7c\xf3\xc2\x5f\x34\x17\x25\x0c\xbe\x4c\x79\x95\xe7\x23\xd0\xfe\xe9\xc8\xe7\x63\xe4\x15\x6e\x71\x4f\x77\xd1\xa7\x4c\xc6\x0f\xa4\x3c\xf8\x38\x4d\xfc\x28\xcf\xf0\x75\xa6\x4e\x2e\xd3\x2d\x4d\x96\xb3\x87\x8e\x13\x1f\xbc\x71\x7d\x20\x1c\x6c\xf0\xb6\xfb\x82\xdf\x25\x68\xea\x4a\xfc\xfe\x17\x92\xe2\xa7\x29\xd8\x14\xa3\x76\x18\xbe\xe3\xe9\x83\x77\xfd\xec\x60\x5c\x64\x1b\x93\x0a\x02\x92\x0e\xca\x83\xc7\x52\x10\x6f\xd9\xda\xf3\x2f\xbe\x05\x8c\x04\x26\xcc\x5d\x30\x32\x1d\x07\x1a\xdd\x75\x53\x3d\x66\xec\xa8\x4b\xd5\x4d\xe9\xbe\x49\xc1\x4c\x82\x5f\x04\x28\xf8\x45\x00\x79\xf6\xfc\x24\xc8\x88\x70\x1e\x16\x6c\xdd\xdd\xeb\x28\x3b\x3e\xf8\x7c\x3e\xae\x99\xc4\x59\x7c\xb7\x24\xca\xc8\x17\xa3\x5e\xcc\x80\x1d\xe6\x49\x2c\x5d\x98\xc3\xc6\x44\x76\xd8\x45\xad\xc7\x57\x92\xc3\x22\x79\x67\x28\xca\xd2\xa7\x95\xe3\x99\x88\x4d\x35\xcc\x5b\x37\x4b\x7e\x23\x09\x46\xc8\x78\x7a\x2a\x3b\xc7\x6d\x5a\x48\x5f\xd4\x04\xe2\xad\xc3\x1c\xf8\xb5\xfa\xbc\x8b\x6b\x63\x0b\x86\x19\x7a\x45\x75\x04\x48\x3a\x75\xbe\x58\x61\xfe\xb3\x29\x42\x32\xd5\xd8\x11\x93\x7e\x54\x65\x02\x52\x9e\xbf\x4e\xed\xb1\xeb\x49\x18\xfe\xaa\x06\xde\x16\x0f\x4a\x39\x44\xb6\xce\xf4\xd6\x76\xa3\x77\xd2\x38\x5e\xd6\xdd\xd0\x4e\xaf\xb0\xe3\xba\x07\x2b\x05\xa7\x18\x5f\x00\xd0\x5b\xe1\x5a\x53\x24\x8e\x07\x8e\x33\xdf\xb2\x1e\x8c\x1a\xb9\x90\x7b\x5d\xad\xf3\x72\x02\x4b\x37\x16\xda\xe0\x88\xe4\x8b\xda\x18\x8c\xd2\x43\xb8\x66\xbe\x7e\xa8\xb0\x9e\xf1\x45\x19\x58\xe4\xa2\x41\x46\x6c\xcd\x40\x3e\xd3\xc2\x60\x88\x93\x4d\x7c\xc5\x20\xf9\x3d\xfe\xe5\xc2\xbd\x5f\x7e\xce\x4f\x5f\xb4\x73\xbe\x92\xc3\x67\x58\x29\xdf\x95\x68\xea\xd8\x02\x37\x5d\xfd\xa1\x91\x61\x40\xac\x73\x4f\x35\x7f\x6c\x6c\x6d\xd9\x1d\xea\x45\x86\xc7\xe4\xbb\x95\x3a\x2a\xdf\x97\x62\x2b\x7f\x3c\xa3\xbc\xa7\xb9\xde\x8b\x2c\xe1\xd2\xeb\x1e\xcb\xdb\x40\xdf\x2d\x28\x1f\x8f\xd9\xd3\x11\xf7\x04\x3c\x11\xb5\x4d\x80\x23\xf1\xac\xff\xfe\xc1\x8e\x06\x73\x09\x18\x62\x80\xdb\x16\x43\xe9\xcb\x2f\x9a\x41\xe0\x24\x0f\xa7\xc1\x64\xa0\xbb\x1f\xbc\x22\x7c\x04\x8f\x11\xf7\x1d\x5f\x05\xe5\xc7\x4c\xf8\x8d\x60\x0d\xf7\xd1\x03\xcd\x3e\x16\xa0\xc6\xa3\x23\x13\x0a\xfb\x7d\x60\x85\x1e\x47\xa3\xf8\xfc\x1c\xc3\x43\x48\x3e\x83\xb2\xdb\xe2\x5b\x54\xee\xfb\x27\x1f\xf0\x3b\x64\x0a\xf2\x2e\x51\xb6\x6c\xda\x86\x96\x07\x26\x62\x7b\xab\xe8\x95\xe5\x75\x13\x15\x60\x02\x3f\x64\x3b\xbd\x29\x66\x75\x2e\x90\x4d\xf2\x03\x5f\x1b\xf3\xb5\xfa\xa6\xcf\xd7\x56\x87\x2d\x90\x0b\xb5\x5b\xdf\x70\x81\xd5\x3a\xb5\x82\xa0\xa6\xd6\x69\xe6\x1c\xef\x89\x2a\x0a\x7c\xa5\x39\x01\x2c\xdc\x1c\x7c\x57\x8b\xd0\xb5\xdb\x66\x3c\x55\x5c\xf3\x91\xec\xf4\x2d\xb2\xd3\x1b\xce\x1e\xf7\x60\xa3\x72\xd5\x06\x83\x3a\x56\xef\xb6\x2d\x47\x75\x5e\xf2\xb5\xc5\x21\xbc\x61\x6e\x55\xe6\xdb\x11\xde\x5e\x53\xe6\x08\x6b\x80\x1c\x23\x00\xb0\xc7\xb1\x10\xd6\xaa\x0a\x28\x56\x61\x8d\x37\x94\x75\x0c\x1a\x11\x00\x43\x78\x7c\x25\xea\x48\x0d\x3d\xb3\x87\xa3\x52\x9f\xcd\x68\x54\xcd\xfc\xef\xf8\xa6\x92\x42\x5f\xc9\xcf\x00\x6a\xde\x34\x3d\x3f\x5d\xbf\x65\x71\x6b\x71\xe7\xd0\xf4\xab\xe5\xb3\xb8\xb5\xb8\x1b\x61\x4a\xa0\xc7\xa8\x12\xe8\xe3\xb8\xda\xf0\x9d\x69\xea\xab\xdd\x2d\xfa\x1d\x6d\x50\xd7\xe1\xc5\x35\xdf\xbf\xbe\x76\x05\xa3\x1e\x47\x35\x43\x0a\x1d\x56\x9e\xea\x79\x41\x42\x44\x39\xd9\xf5\x19\x97\x3c\xd8\xf7\xa8\x6e\xd8\xf9\xa8\xfa\xd4\x4e\xc1\x53\x7c\x6c\x74\x9e\xef\x16\x77\x65\xcf\x31\xe3\xab\x0c\x1e\xe6\xb0\xad\x77\x06\x96\xfe\x0a\xb0\xf4\x35\x81\xa5\x37\xf2\x61\xa4\x71\xab\x74\xe8\x6c\xca\x3e\x47\xa4\x40\xd0\xca\xab\x33\x5a\x01\xce\x2e\xf2\xa9\x5a\xb0\xce\x64\x2a\x65\xeb\x2e\x64\xc1\x27\x68\x41\x3f\xd9\x24\x82\xf7\xa9\x03\x99\x6a\x8d\xd5\x00\x39\xfd\x16\x87\x85\xbc\x33\xc7\x8a\x01\x8d\xe1\xbd\xe4\x04\xb0\x78\x0e\x88\x60\x8d\x47\xc2\x29\x8e\x77\x81\x08\xfc\x26\x66\x94\xc2\xc1\x3c\xb0\x30\x2e\x82\x7b\x97\xef\xba\x49\xc0\x6d\x2e\x9b\xe9\x28\xa4\x75\x6f\x80\xd6\xf3\x10\x4e\x3b\xed\x04\x95\xc2\x56\x44\x53\x93\xd8\x62\x7d\x8a\xc7\x3e\xda\x88\xd0\x62\x7b\x88\x07\x9f\x6e\x14\xd8\xcf\x7e\x89\x44\xc1\x44\x7a\x85\xcc\x2a\x39\x26\x6f\xe1\x95\x5d\x4b\x5b\x19\x2c\x51\x6a\xd3\xd3\xbc\xe8\xb3\x28\x9a\x67\x77\xa7\xdc\x35\x50\xcd\x0f\xef\x33\x6a\x8b\x10\x4c\x2d\x64\x25\x7e\x71\x5e\x23\x57\x04\x50\xde\x1e\x10\x4f\xd2\x3a\xac\x0c\xa5\xc1\x7d\xb3\x2f\x6a\xe0\x2d\xf4\x89\x60\x6e\x47\x5f\xac\xb4\xc7\x5a\xbe\xf0\xd1\x4a\x3f\x9b\x00\xc7\x70\x74\xc7\xd8\xad\xba\x2c\x44\xe7\xf0\xad\x97\x7c\x80\x5e\x06\x57\x0c\x47\xa0\xf0\x7c\x87\xdf\x58\x09\xdc\x8f\x86\x72\x38\xfa\xf0\x6d\x27\x0d\xe4\x1b\xb5\x10\xd4\x09\x3e\x88\xc5\xe1\xd0\x72\xd7\x68\x0a\x45\xde\x3a\x68\x18\x72\x8f\x7f\x02\xfa\x41\xd7\x52\x8c\x8b\xe9\x37\x89\xff\xbf\x3c\xcb\x1c\x0e\xc0\x3f\xce\x7c\xa4\xff\x7f\x97\xc7\x99\x87\x96\x59\xf7\x3a\x33\x5e\x9f\x9d\xe1\x72\x40\xbc\x8f\x23\xc7\x55\xb4\x9f\x51\x23\xdc\xa7\xc8\x88\x5d\xf9\xc8\xf2\x66\x5f\xb3\xf8\x8a\xd5\x06\x5b\x74\xd8\x5f\x70\x9f\x23\xea\x4d\x6a\x8c\xdf\x10\x8a\x87\x20\x39\x63\x6f\x91\xe4\xab\x35\x22\xd5\x67\x2f\x4a\xb5\x1e\xcd\x60\x92\x50\x17\x8d\xe5\x8d\xbe\xfd\xca\x9b\x5a\xb7\xf6\x60\xc8\xf1\xe6\x8e\x46\x2d\x95\xe4\xa6\xaf\x5d\x15\x99\x64\x26\x0a\x18\x4c\x45\x72\xc2\xeb\xf3\x92\x23\xaf\x91\xe2\x79\x7e\x49\x69\xfe\x38\x0a\x23\x18\xb1\x36\x13\x77\x1d\x34\x0a\xa0\x49\x5e\x15\x8c\x65\x18\x9f\x2a\xb9\xe1\xa7\x5e\x25\x47\xbf\x9a\x89\x0f\x66\x4a\xce\x1c\xf1\x43\x88\x72\x63\xe3\xd3\xf9\xa5\x75\xdb\xf7\x6d\x35\xdf\xf5\xd3\xef\xec\xba\xd2\x11\xb4\xb9\xfd\x99\x76\xd3\xcf\xc0\x76\x3b\x6b\xf8\x7a\xf7\xb9\x76\x07\xdf\x40\x19\xc0\xc9\x23\x01\xa9\x7b\xdd\xe2\x25\x7e\x6b\xe1\x86\x79\x64\xd6\xf1\xc7\x99\x2f\x88\xc5\x14\xe9\xf5\xa9\x96\xe0\xdb\x98\x6a\x1d\xc1\x27\x34\x8f\xae\x02\x43\x8e\xbe\xb5\xe9\x8b\x14\xaf\x28\x0a\x90\xab\xef\xf5\xf6\xf2\x94\xaa\xbc\x55\x7b\xf3\xf6\x9a\x92\x8b\xf6\x20\x0e\x23\x5d\x17\xf6\x18\xe8\x17\x29\xed\x03\x06\xa7\x17\xee\x9b\x9f\xc1\x4a\x6b\x93\xfc\x3d\xc1\x2c\xf8\x54\xb6\x36\x4e\xe3\x6f\xf4\x6b\x59\x6a\x30\x55\x5a\xe5\xd7\xde\x39\xf8\x77\xdb\x59\x3b\xc1\x55\xe4\x01\xd9\xeb\xbb\xbe\xba\x02\xa3\xc3\x28\xb6\xdc\xe2\xa0\x71\x87\x52\x48\xef\xe1\x59\x19\x75\xf0\x85\xaf\xf0\x86\x6d\x05\x87\xca\x03\x63\x9d\xbc\x6b\x18\x3f\xc2\x14\x02\x66\xb2\xff\xec\xf1\xb5\xa8\x61\xe7\x64\x1a\x57\x88\x5e\x61\x8b\x2a\x4d\x87\x01\x3c\xf4\xfe\x9a\x18\x05\x4c\x19\x77\x36\x6f\x55\xc6\x63\xd3\xb7\xc2\x3e\xf4\xb9\xe1\x00\xe4\x5e\x5c\x6b\x01\x84\x7d\x28\x3d\x00\x9a\xfe\xdc\xad\x02\x0c\x79\x8a\x66\x0f\xbe\x82\x1a\x7d\xfe\xd4\x6a\xda\xd7\xdc\x9a\x9d\x68\xdb\xf8\xda\xa2\xde\x31\x7a\x8f\x4c\x16\xb4\x0c\x7c\xea\x93\xc3\x41\x91\x76\xc4\x45\x61\x27\x38\xa1\xf8\xfb\x8b\x0f\x7e\x1e\xd9\x10\xcc\x26\xf7\x45\x26\x2f\xf0\x04\x75\x60\xf0\x5f\x20\x8c\x77\x5c\x89\xc6\x3d\xae\x41\xe3\x3e\x02\x2e\x4e\x60\xe3\xe7\xd7\xf8\x25\x2c\xc4\x8d\x98\x43\xcb\x94\x8a\x6c\xc2\x92\x37\xfc\x38\x45\x88\x83\x62\xee\x09\xc3\x7d\xb2\x72\x92\x34\xfc\x27\xbf\xc3\x6e\xf9\x63\xdd\xc1\x41\xe0\x73\xc3\x23\xcd\xe7\x86\xdf\x04\xf7\xb9\x53\x1f\xe9\x1e\x97\x7a\xcf\xfc\x77\x1c\x9b\xf2\xed\x56\xbe\x5b\xde\x7d\x8b\x2f\xb3\x7e\x1f\xd4\x08\x3f\xf0\x1d\xe7\x0e\xdb\xd0\xef\x89\x0e\x9a\x30\x66\x19\x6d\x99\x6a\x71\x04\x31\xee\xb3\x82\xd1\x73\xcd\x40\xbf\x7c\x9e\x56\x8f\x95\xe8\x7b\xc2\x43\x62\xf6\xcc\xd6\x91\x72\xc8\x68\x6d\x60\x1c\xd2\x1e\x7d\x68\x57\x3f\xee\xa6\xb1\xed\xee\x53\x86\xbf\x22\xdb\x8f\x70\xf2\x2b\xba\xc3\xcf\xe7\x72\xd0\xb9\x55\x89\xbf\x77\x3c\xfe\xd0\xb1\x82\xd9\x9b\xf1\xb0\x08\x8c\x9e\x97\x87\x29\x40\x5f\x97\x37\xc6\x20\x57\x9c\x38\xbe\x3b\x5b\xab\xf9\x5b\xae\x41\x21\xca\x3b\x7d\x0b\x7b\xb7\x1b\x77\xf4\xcd\xb5\xa8\x92\x7c\xea\xcd\x7d\xd7\x69\x5c\xd9\x6e\xeb\xb9\x45\xb4\xdb\x47\x93\x8b\xf8\xfb\xae\xdc\x51\xe3\xf2\x31\x36\x7e\xc8\x8c\x7e\xa6\x6f\xf1\xd3\xad\x95\x5c\x2b\x82\x36\xcc\xc1\xcc\xcf\xed\xa2\x11\x94\x62\xca\x71\xab\x74\x57\x6d\xf9\x58\xd6\x8f\xd1\xf0\xe2\x50\x0e\xce\xe6\x3f\x23\x27\x44\x72\xc8\x99\x2f\xf0\x7b\x7a\x80\x0a\x3b\x96\x02\xe3\x72\x23\x28\xa2\xf3\x26\x20\xa6\xd7\xbf\xbd\xbd\x1a\x40\x4e\x6c\x50\x2d\x99\xd8\xd0\xf1\xc7\xb6\xc3\xed\x2b\xae\x1c\x37\x05\xb8\x6f\xa6\x67\x20\x90\x47\x27\x20\x34\xe4\x3d\xb3\x20\x9e\xc9\x86\x94\xda\x8a\x7c\x2b\x3b\x46\xe9\x4c\x7e\xc7\x40\xc1\xeb\x8e\x02\x65\x8f\x3b\x8e\x7a\xad\xc3\x3e\x6b\x71\x43\x78\x7e\x20\x21\x02\x01\x3f\x90\x50\xdb\xc9\xe1\x19\x34\xa9\xac\xf7\x55\xa1\x82\xa3\xc0\xbf\xd3\x2c\x03\x35\x10\xdf\xb2\x41\x68\xd3\x6e\x98\x44\xb8\x95\x93\xde\xce\xf0\x2b\x5a\x3a\xdd\x88\xbc\x5f\x04\xd6\x6f\x43\x7e\xac\x5e\x6a\x18\xf0\x72\xe1\x10\x63\x06\xa5\x57\x67\xfe\xdd\x4b\xd8\x9e\x06\x93\x59\x57\xb7\xa5\xb3\x54\xe9\x6c\xde\x52\x5e\x04\xcc\x5f\xc9\xef\xec\x42\xa4\x7c\xf0\x8f\xbf\xb3\x3d\x98\x44\xd8\x94\xce\x64\xd4\xd2\xb6\x82\xf5\x30\xc0\x8b\x64\x4c\x63\xdc\xa0\x95\x6f\x07\xe0\xca\xb8\x87\xec\xd6\x3e\x98\x13\xec\x10\xff\xf5\x0a\x7f\x3e\xbb\xde\xf9\x5c\x9e\xec\x99\xa1\xf4\xe4\x62\x18\x9c\x5c\x16\x2d\x30\x5b\xb4\xf2\xb6\x0a\xff\xbb\x61\x3f\xae\x2b\x09\xf7\x9e\xe5\x75\x44\x7b\xc5\x4e\x2e\xdb\x68\xd2\xc3\xfb\xe8\x02\x41\x93\x15\x4c\x3c\x27\x16\x03\x94\x7f\x94\x8b\x5d\xe0\x56\xf8\x4d\x7e\xab\x1d\xcf\x37\xd3\x58\x70\xe0\xae\xc6\x83\x67\xef\x24\x27\x80\x99\x7a\x60\xc9\x86\x8e\x10\x47\x0b\x75\x3c\xda\xbf\xeb\x1e\xea\x0f\x43\x59\xc4\x85\x45\x39\xc8\xcf\x6c\x2d\x77\x2f\x06\x41\x18\x06\x1b\x4a\x21\x61\x5e\xf6\x43\x24\xa7\xb9\xb2\x89\x81\x5b\x51\x83\x4f\xc1\x6f\x67\x01\x2c\x44\xf1\xe0\x29\x72\x19\x83\x94\x7f\x2e\xc4\x2a\xf9\x28\x31\x0d\x9f\x06\x8f\xd3\x9a\xf9\x31\x08\xa3\x89\xee\xff\x3c\x92\x27\xe2\xe4\x92\x94\x55\xe2\x08\x22\x79\xe2\x2e\x80\x7d\xda\xb5\x8b\xa7\x8f\xc2\x87\xe5\xd8\x22\xe4\x01\xf8\x21\x3a\x2e\xfc\x49\x5f\x9d\xd3\x71\xc0\xa8\x41\x6d\xfe\x4d\x1f\xac\x93\xdf\x61\xbb\x62\xf6\x90\xa6\xbb\xff\xe4\x5a\xff\x5b\xa2\xc1\x16\xbe\x09\xcd\xc0\xcb\xf5\x5f\xd3\x90\x7b\xc3\x43\xe7\x67\xbf\x07\x78\xc1\x95\x69\x46\x88\xdc\x9d\x1e\x7e\xce\x40\x51\x85\x9b\xd7\x7c\x13\xc7\xe3\x89\x7e\x3c\x8c\xa8\xa8\xa9\x11\xa2\x9a\x0d\xdf\x41\xcc\x7e\xcc\xfc\x2b\x97\xb8\x84\x27\x05\x55\xa7\xef\x62\xc9\xb7\x22\x7e\x74\x2f\x5c\x26\x1f\xfb\xa6\x59\x7f\x4a\xf2\x25\xcf\x89\xfe\x26\x78\x42\x56\xe2\x75\x11\x93\x46\xc9\x44\x7e\x72\xea\x07\x6e\xf8\x07\xd2\x52\x89\x81\xe0\x71\xb6\x1f\x36\xc8\x90\xaf\x0d\x23\x63\x85\x0c\x7e\x7b\x18\x3f\x0b\xfc\x2c\xf2\x03\x7e\xed\xf1\x6b\x5f\x96\x77\x52\x19\x1c\x86\xaa\x93\xd6\xb7\x42\xce\x01\xbf\xf9\xb5\x31\x7c\xea\x1d\xfd\xe8\xb3\x7e\xf6\x03\x4f\xc2\xc9\xc7\x8d\x91\x6f\x3f\x28\x5f\x3e\xfb\xf1\xdc\x7f\x01\xe4\x11\xfb\xc7\x0e\x9a\x85\x14\xe5\x70\xf7\x9a\x25\xc9\x47\x60\x13\xa4\xcb\x6a\x83\x92\xa6\x5c\x1e\x87\x66\x4a\x92\xf2\xda\x7c\x9f\xf9\x71\x69\x0a\xb9\x7e\x54\x9a\x4a\xfe\x5f\x00\x00\x00\xff\xff\x61\x73\x28\xd3\xa2\x8c\x00\x00") func confLocaleLocale_enUsIniBytes() ([]byte, error) { return bindataRead( @@ -787,7 +787,7 @@ func confLocaleLocale_enUsIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 35227, mode: os.FileMode(420), modTime: time.Unix(1438778210, 0)} + info := bindataFileInfo{name: "conf/locale/locale_en-US.ini", size: 36002, mode: os.FileMode(420), modTime: time.Unix(1438872339, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -987,7 +987,7 @@ func confLocaleLocale_zhCnIni() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "conf/locale/locale_zh-CN.ini", size: 34628, mode: os.FileMode(493), modTime: time.Unix(1438751462, 0)} + info := bindataFileInfo{name: "conf/locale/locale_zh-CN.ini", size: 34628, mode: os.FileMode(493), modTime: time.Unix(1438834795, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/public/css/gogs.min.css b/public/css/gogs.min.css index eab009f7..1690df33 100644 --- a/public/css/gogs.min.css +++ b/public/css/gogs.min.css @@ -1 +1 @@ -@font-face{font-family:octicons;src:url(../fonts/octicons.eot?#iefix&v=345f8bad9c5003db196d08f05e7f030fd2a32ff6)format('embedded-opentype'),url(../fonts/octicons.woff?v=345f8bad9c5003db196d08f05e7f030fd2a32ff6)format('woff'),url(../fonts/octicons.ttf?v=345f8bad9c5003db196d08f05e7f030fd2a32ff6)format('truetype'),url(../fonts/octicons.svg?v=345f8bad9c5003db196d08f05e7f030fd2a32ff6#octicons)format('svg');font-weight:400;font-style:normal}.mega-octicon,.octicon{font:normal normal normal 16px/1 octicons;display:inline-block;text-decoration:none;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.mega-octicon{font-size:32px}.octicon-alert:before{content:'\f02d'}.octicon-alignment-align:before{content:'\f08a'}.octicon-alignment-aligned-to:before{content:'\f08e'}.octicon-alignment-unalign:before{content:'\f08b'}.octicon-arrow-down:before{content:'\f03f'}.octicon-arrow-left:before{content:'\f040'}.octicon-arrow-right:before{content:'\f03e'}.octicon-arrow-small-down:before{content:'\f0a0'}.octicon-arrow-small-left:before{content:'\f0a1'}.octicon-arrow-small-right:before{content:'\f071'}.octicon-arrow-small-up:before{content:'\f09f'}.octicon-arrow-up:before{content:'\f03d'}.octicon-beer:before{content:'\f069'}.octicon-book:before{content:'\f007'}.octicon-bookmark:before{content:'\f07b'}.octicon-briefcase:before{content:'\f0d3'}.octicon-broadcast:before{content:'\f048'}.octicon-browser:before{content:'\f0c5'}.octicon-bug:before{content:'\f091'}.octicon-calendar:before{content:'\f068'}.octicon-check:before{content:'\f03a'}.octicon-checklist:before{content:'\f076'}.octicon-chevron-down:before{content:'\f0a3'}.octicon-chevron-left:before{content:'\f0a4'}.octicon-chevron-right:before{content:'\f078'}.octicon-chevron-up:before{content:'\f0a2'}.octicon-circle-slash:before{content:'\f084'}.octicon-circuit-board:before{content:'\f0d6'}.octicon-clippy:before{content:'\f035'}.octicon-clock:before{content:'\f046'}.octicon-cloud-download:before{content:'\f00b'}.octicon-cloud-upload:before{content:'\f00c'}.octicon-code:before{content:'\f05f'}.octicon-color-mode:before{content:'\f065'}.octicon-comment-add:before,.octicon-comment:before{content:'\f02b'}.octicon-comment-discussion:before{content:'\f04f'}.octicon-credit-card:before{content:'\f045'}.octicon-dash:before{content:'\f0ca'}.octicon-dashboard:before{content:'\f07d'}.octicon-database:before{content:'\f096'}.octicon-device-camera:before{content:'\f056'}.octicon-device-camera-video:before{content:'\f057'}.octicon-device-desktop:before{content:'\f27c'}.octicon-device-mobile:before{content:'\f038'}.octicon-diff:before{content:'\f04d'}.octicon-diff-added:before{content:'\f06b'}.octicon-diff-ignored:before{content:'\f099'}.octicon-diff-modified:before{content:'\f06d'}.octicon-diff-removed:before{content:'\f06c'}.octicon-diff-renamed:before{content:'\f06e'}.octicon-ellipsis:before{content:'\f09a'}.octicon-eye-unwatch:before,.octicon-eye-watch:before,.octicon-eye:before{content:'\f04e'}.octicon-file-binary:before{content:'\f094'}.octicon-file-code:before{content:'\f010'}.octicon-file-directory:before{content:'\f016'}.octicon-file-media:before{content:'\f012'}.octicon-file-pdf:before{content:'\f014'}.octicon-file-submodule:before{content:'\f017'}.octicon-file-symlink-directory:before{content:'\f0b1'}.octicon-file-symlink-file:before{content:'\f0b0'}.octicon-file-text:before{content:'\f011'}.octicon-file-zip:before{content:'\f013'}.octicon-flame:before{content:'\f0d2'}.octicon-fold:before{content:'\f0cc'}.octicon-gear:before{content:'\f02f'}.octicon-gift:before{content:'\f042'}.octicon-gist:before{content:'\f00e'}.octicon-gist-secret:before{content:'\f08c'}.octicon-git-branch-create:before,.octicon-git-branch-delete:before,.octicon-git-branch:before{content:'\f020'}.octicon-git-commit:before{content:'\f01f'}.octicon-git-compare:before{content:'\f0ac'}.octicon-git-merge:before{content:'\f023'}.octicon-git-pull-request-abandoned:before,.octicon-git-pull-request:before{content:'\f009'}.octicon-globe:before{content:'\f0b6'}.octicon-graph:before{content:'\f043'}.octicon-heart:before{content:'\2665'}.octicon-history:before{content:'\f07e'}.octicon-home:before{content:'\f08d'}.octicon-horizontal-rule:before{content:'\f070'}.octicon-hourglass:before{content:'\f09e'}.octicon-hubot:before{content:'\f09d'}.octicon-inbox:before{content:'\f0cf'}.octicon-info:before{content:'\f059'}.octicon-issue-closed:before{content:'\f028'}.octicon-issue-opened:before{content:'\f026'}.octicon-issue-reopened:before{content:'\f027'}.octicon-jersey:before{content:'\f019'}.octicon-jump-down:before{content:'\f072'}.octicon-jump-left:before{content:'\f0a5'}.octicon-jump-right:before{content:'\f0a6'}.octicon-jump-up:before{content:'\f073'}.octicon-key:before{content:'\f049'}.octicon-keyboard:before{content:'\f00d'}.octicon-law:before{content:'\f0d8'}.octicon-light-bulb:before{content:'\f000'}.octicon-link:before{content:'\f05c'}.octicon-link-external:before{content:'\f07f'}.octicon-list-ordered:before{content:'\f062'}.octicon-list-unordered:before{content:'\f061'}.octicon-location:before{content:'\f060'}.octicon-gist-private:before,.octicon-git-fork-private:before,.octicon-lock:before,.octicon-mirror-private:before{content:'\f06a'}.octicon-logo-github:before{content:'\f092'}.octicon-mail:before{content:'\f03b'}.octicon-mail-read:before{content:'\f03c'}.octicon-mail-reply:before{content:'\f051'}.octicon-mark-github:before{content:'\f00a'}.octicon-markdown:before{content:'\f0c9'}.octicon-megaphone:before{content:'\f077'}.octicon-mention:before{content:'\f0be'}.octicon-microscope:before{content:'\f089'}.octicon-milestone:before{content:'\f075'}.octicon-mirror-public:before,.octicon-mirror:before{content:'\f024'}.octicon-mortar-board:before{content:'\f0d7'}.octicon-move-down:before{content:'\f0a8'}.octicon-move-left:before{content:'\f074'}.octicon-move-right:before{content:'\f0a9'}.octicon-move-up:before{content:'\f0a7'}.octicon-mute:before{content:'\f080'}.octicon-no-newline:before{content:'\f09c'}.octicon-octoface:before{content:'\f008'}.octicon-organization:before{content:'\f037'}.octicon-package:before{content:'\f0c4'}.octicon-paintcan:before{content:'\f0d1'}.octicon-pencil:before{content:'\f058'}.octicon-person-add:before,.octicon-person-follow:before,.octicon-person:before{content:'\f018'}.octicon-pin:before{content:'\f041'}.octicon-playback-fast-forward:before{content:'\f0bd'}.octicon-playback-pause:before{content:'\f0bb'}.octicon-playback-play:before{content:'\f0bf'}.octicon-playback-rewind:before{content:'\f0bc'}.octicon-plug:before{content:'\f0d4'}.octicon-file-add:before,.octicon-file-directory-create:before,.octicon-gist-new:before,.octicon-plus:before,.octicon-repo-create:before{content:'\f05d'}.octicon-podium:before{content:'\f0af'}.octicon-primitive-dot:before{content:'\f052'}.octicon-primitive-square:before{content:'\f053'}.octicon-pulse:before{content:'\f085'}.octicon-puzzle:before{content:'\f0c0'}.octicon-question:before{content:'\f02c'}.octicon-quote:before{content:'\f063'}.octicon-radio-tower:before{content:'\f030'}.octicon-repo-delete:before,.octicon-repo:before{content:'\f001'}.octicon-repo-clone:before{content:'\f04c'}.octicon-repo-force-push:before{content:'\f04a'}.octicon-gist-fork:before,.octicon-repo-forked:before{content:'\f002'}.octicon-repo-pull:before{content:'\f006'}.octicon-repo-push:before{content:'\f005'}.octicon-rocket:before{content:'\f033'}.octicon-rss:before{content:'\f034'}.octicon-ruby:before{content:'\f047'}.octicon-screen-full:before{content:'\f066'}.octicon-screen-normal:before{content:'\f067'}.octicon-search-save:before,.octicon-search:before{content:'\f02e'}.octicon-server:before{content:'\f097'}.octicon-settings:before{content:'\f07c'}.octicon-log-in:before,.octicon-sign-in:before{content:'\f036'}.octicon-log-out:before,.octicon-sign-out:before{content:'\f032'}.octicon-split:before{content:'\f0c6'}.octicon-squirrel:before{content:'\f0b2'}.octicon-star-add:before,.octicon-star-delete:before,.octicon-star:before{content:'\f02a'}.octicon-steps:before{content:'\f0c7'}.octicon-stop:before{content:'\f08f'}.octicon-repo-sync:before,.octicon-sync:before{content:'\f087'}.octicon-tag-add:before,.octicon-tag-remove:before,.octicon-tag:before{content:'\f015'}.octicon-telescope:before{content:'\f088'}.octicon-terminal:before{content:'\f0c8'}.octicon-three-bars:before{content:'\f05e'}.octicon-thumbsdown:before{content:'\f0db'}.octicon-thumbsup:before{content:'\f0da'}.octicon-tools:before{content:'\f031'}.octicon-trashcan:before{content:'\f0d0'}.octicon-triangle-down:before{content:'\f05b'}.octicon-triangle-left:before{content:'\f044'}.octicon-triangle-right:before{content:'\f05a'}.octicon-triangle-up:before{content:'\f0aa'}.octicon-unfold:before{content:'\f039'}.octicon-unmute:before{content:'\f0ba'}.octicon-versions:before{content:'\f064'}.octicon-remove-close:before,.octicon-x:before{content:'\f081'}.octicon-zap:before{content:'\26A1'}body{font-family:'Helvetica Neue',Arial,Helvetica,sans-serif,'微软雅黑';background-color:#FAFAFA}img{border-radius:3px}.full.height{padding:0;margin:0 0 -87px 0;min-height:100%}.following.bar{z-index:900;left:0;width:100%;padding:.7em 0}.following.bar.light{background-color:#fff;border-bottom:1px solid #DDD;box-shadow:0 2px 3px rgba(0,0,0,.04)}.following.bar .ui.secondary.menu{height:30px}.following.bar .column .menu{margin-top:0}.following.bar .brand{float:left;margin-right:5px}.following.bar .head.link.item{padding-right:0!important}.following.bar .head.link.item .dropdown.icon,.following.bar .head.link.item .menu .octicon{margin-right:5px}.following.bar .user.avatar{padding:0;margin-top:1px}.following.bar .searchbox{background-color:#f4f4f4!important}.following.bar .searchbox:focus{background-color:#e9e9e9!important}.following.bar .octicon{width:16px;opacity:1!important;text-align:center}.ui.left{float:left}.ui.right{float:right}footer{margin-top:40px!important;background-color:#fff;border-top:1px solid #d6d6d6;clear:both;width:100%;color:#888}footer .fa{width:16px;text-align:center;color:#428bca}footer .ui.language.dropdown{z-index:10000}footer .links>*{border-left:1px solid #d6d6d6;padding-left:8px;margin-left:5px}footer .links>:first-child{border-left:none}.hide{display:none}.center{text-align:center}.text-error{color:#d95c5c!important}.img-1{width:2px;height:2px}.img-2{width:4px;height:4px}.img-3{width:6px;height:6px}.img-4{width:8px;height:8px}.img-5{width:10px;height:10px}.img-6{width:12px;height:12px}.img-7{width:14px;height:14px}.img-8{width:16px;height:16px}.img-9{width:18px;height:18px}.img-10{width:20px;height:20px}.img-11{width:22px;height:22px}.img-12{width:24px;height:24px}.img-13{width:26px;height:26px}.img-14{width:28px;height:28px}.img-15{width:30px;height:30px}.img-16{width:32px;height:32px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.home{padding-bottom:120px}.home .logo{max-width:250px}.home .hero h1,.home .hero h2{font-family:'PT Sans Narrow',sans-serif}.home .hero h1{font-size:7em}.home .hero h2{font-size:4em}.home .hero .octicon{color:#d9453d;font-size:60px;margin-right:10px}.home .hero.header{font-size:24px}.home p.large{font-size:20px}.home .stackable{padding-top:30px}.home a{color:#d9453d}.install{padding-top:45px;padding-bottom:120px}.install .attached.header{background:#f0f0f0}.install form label{text-align:right;width:40%!important}.install form input{width:35%!important}.install form .field{text-align:left}.install form .field .help{margin-left:41%}.install form .field.optional .title{margin-left:38%}.install .ui .checkbox{margin-left:40%!important}.install .ui .checkbox label{width:auto!important}.form .help{color:#999;padding-top:.6em;padding-bottom:.6em;display:inline-block}.repository{padding-top:15px;padding-bottom:120px}.repository .head{height:75px;padding-top:20px;background-color:#FCFCFC}.repository .head .mega-octicon{width:30px}.repository .head .fork-flag,.repository .head a{font-weight:300}.repository .head .ui.label{margin-top:5px;vertical-align:top}.repository .head .fork-flag{margin-left:38px;display:block;font-size:11px;line-height:10px;white-space:nowrap}.repository .head .button{margin-left:10px}.repository .head .button i{margin-right:5px}.repository .head .num{font-weight:700}.repository .head .octicon{height:5px}.repository .navbar{height:60px;padding-top:20px}.repository .navbar .ui.secondary.menu .item{margin-left:-10px;margin-top:-7px}.repository .navbar .ui.secondary.menu .item>.input .color-picker,.repository .navbar .ui.secondary.menu .item>.input .new-label-input{background-color:#fff;border:1px solid rgba(0,0,0,.15)}.repository .navbar .ui.secondary.menu .item.input{margin-right:-7px}.repository .navbar .ui.secondary.menu .item .new-label-input{width:150px}.repository .navbar .ui.secondary.menu .item .color-picker{height:35px;width:auto;padding-left:30px}.repository .navbar .ui.secondary.menu .item .minicolors-swatch.minicolors-sprite{top:10px;left:10px;width:15px;height:15px}.repository .navbar .ui.secondary.menu .item.precolors{padding-left:0;padding-right:0;margin-right:10px;width:120px}.repository .navbar .ui.secondary.menu .item.precolors .color{float:left;width:15px;height:15px}.repository .filter.menu .label.color{margin-left:17px;padding:0 8px}.repository .filter.menu .octicon{float:left;margin-left:-5px;margin-right:-7px}.repository .filter.menu .menu{max-height:300px;overflow-x:auto;right:0!important;left:auto!important}.repository .filter.menu .menu .clickable .name{padding-left:15px!important}.repository .page.buttons{padding-top:15px}.repository .issue.list{clear:both;list-style:none}.repository .issue.list>.item{padding-top:15px;padding-bottom:10px;border-bottom:1px dashed #AAA}.repository .issue.list>.item .title{color:#444;font-size:15px;font-weight:700;margin:0 6px}.repository .issue.list>.item .title:hover{color:#000}.repository .issue.list>.item .comment{padding-right:10px;color:#666}.repository .issue.list>.item .desc{padding-top:5px;color:#999}.repository .issue.list>.item .desc a.milestone{padding-left:5px;color:#999!important}.repository .issue.list>.item .desc a.milestone:hover{color:#000!important}.repository .label.list{clear:both;list-style:none}.repository .label.list .item{padding-top:10px;padding-bottom:10px;border-bottom:1px dashed #AAA}.repository .label.list .item a{font-size:15px;padding-top:5px;padding-right:10px;color:#666}.repository .label.list .item a:hover{color:#000}.repository .label.list .item a.open-issues{margin-right:30px}.repository .milestone.list{clear:both;list-style:none}.repository .milestone.list>.item{padding-top:10px;padding-bottom:10px;border-bottom:1px dashed #AAA}.repository .milestone.list>.item>a{padding-top:5px;padding-right:10px;color:#000}.repository .milestone.list>.item>a:hover{color:#4078c0}.repository .milestone.list>.item .ui.progress{width:40%;padding:0;border:0;margin:0}.repository .milestone.list>.item .ui.progress .bar{height:20px}.repository .milestone.list>.item .meta{color:#999;padding-top:5px}.repository .milestone.list>.item .meta .issue-stats .octicon{padding-left:5px}.repository .milestone.list>.item .meta .overdue{color:red}.repository .milestone.list>.item .operate{margin-top:-15px}.repository .milestone.list>.item .operate>a{font-size:15px;padding-top:5px;padding-right:10px;color:#666}.repository .milestone.list>.item .operate>a:hover{color:#000}.repository .milestone.list>.item .content{padding-top:10px}.repository.new.milestone textarea{height:200px}.edit-label.modal .color-picker{margin-top:-8px!important;height:35px;width:auto!important;padding-left:30px!important}.edit-label.modal .minicolors-swatch.minicolors-sprite{top:1px;left:10px;width:15px;height:15px}.edit-label.modal .precolors{margin-bottom:-11px!important;padding-left:0!important;padding-right:0!important;margin-right:10px!important;width:120px!important}.edit-label.modal .precolors .color{float:left;margin:0!important;width:15px;height:15px} \ No newline at end of file +@font-face{font-family:octicons;src:url(../fonts/octicons.eot?#iefix&v=345f8bad9c5003db196d08f05e7f030fd2a32ff6)format('embedded-opentype'),url(../fonts/octicons.woff?v=345f8bad9c5003db196d08f05e7f030fd2a32ff6)format('woff'),url(../fonts/octicons.ttf?v=345f8bad9c5003db196d08f05e7f030fd2a32ff6)format('truetype'),url(../fonts/octicons.svg?v=345f8bad9c5003db196d08f05e7f030fd2a32ff6#octicons)format('svg');font-weight:400;font-style:normal}.mega-octicon,.octicon{font:normal normal normal 16px/1 octicons;display:inline-block;text-decoration:none;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.mega-octicon{font-size:32px}.octicon-alert:before{content:'\f02d'}.octicon-alignment-align:before{content:'\f08a'}.octicon-alignment-aligned-to:before{content:'\f08e'}.octicon-alignment-unalign:before{content:'\f08b'}.octicon-arrow-down:before{content:'\f03f'}.octicon-arrow-left:before{content:'\f040'}.octicon-arrow-right:before{content:'\f03e'}.octicon-arrow-small-down:before{content:'\f0a0'}.octicon-arrow-small-left:before{content:'\f0a1'}.octicon-arrow-small-right:before{content:'\f071'}.octicon-arrow-small-up:before{content:'\f09f'}.octicon-arrow-up:before{content:'\f03d'}.octicon-beer:before{content:'\f069'}.octicon-book:before{content:'\f007'}.octicon-bookmark:before{content:'\f07b'}.octicon-briefcase:before{content:'\f0d3'}.octicon-broadcast:before{content:'\f048'}.octicon-browser:before{content:'\f0c5'}.octicon-bug:before{content:'\f091'}.octicon-calendar:before{content:'\f068'}.octicon-check:before{content:'\f03a'}.octicon-checklist:before{content:'\f076'}.octicon-chevron-down:before{content:'\f0a3'}.octicon-chevron-left:before{content:'\f0a4'}.octicon-chevron-right:before{content:'\f078'}.octicon-chevron-up:before{content:'\f0a2'}.octicon-circle-slash:before{content:'\f084'}.octicon-circuit-board:before{content:'\f0d6'}.octicon-clippy:before{content:'\f035'}.octicon-clock:before{content:'\f046'}.octicon-cloud-download:before{content:'\f00b'}.octicon-cloud-upload:before{content:'\f00c'}.octicon-code:before{content:'\f05f'}.octicon-color-mode:before{content:'\f065'}.octicon-comment-add:before,.octicon-comment:before{content:'\f02b'}.octicon-comment-discussion:before{content:'\f04f'}.octicon-credit-card:before{content:'\f045'}.octicon-dash:before{content:'\f0ca'}.octicon-dashboard:before{content:'\f07d'}.octicon-database:before{content:'\f096'}.octicon-device-camera:before{content:'\f056'}.octicon-device-camera-video:before{content:'\f057'}.octicon-device-desktop:before{content:'\f27c'}.octicon-device-mobile:before{content:'\f038'}.octicon-diff:before{content:'\f04d'}.octicon-diff-added:before{content:'\f06b'}.octicon-diff-ignored:before{content:'\f099'}.octicon-diff-modified:before{content:'\f06d'}.octicon-diff-removed:before{content:'\f06c'}.octicon-diff-renamed:before{content:'\f06e'}.octicon-ellipsis:before{content:'\f09a'}.octicon-eye-unwatch:before,.octicon-eye-watch:before,.octicon-eye:before{content:'\f04e'}.octicon-file-binary:before{content:'\f094'}.octicon-file-code:before{content:'\f010'}.octicon-file-directory:before{content:'\f016'}.octicon-file-media:before{content:'\f012'}.octicon-file-pdf:before{content:'\f014'}.octicon-file-submodule:before{content:'\f017'}.octicon-file-symlink-directory:before{content:'\f0b1'}.octicon-file-symlink-file:before{content:'\f0b0'}.octicon-file-text:before{content:'\f011'}.octicon-file-zip:before{content:'\f013'}.octicon-flame:before{content:'\f0d2'}.octicon-fold:before{content:'\f0cc'}.octicon-gear:before{content:'\f02f'}.octicon-gift:before{content:'\f042'}.octicon-gist:before{content:'\f00e'}.octicon-gist-secret:before{content:'\f08c'}.octicon-git-branch-create:before,.octicon-git-branch-delete:before,.octicon-git-branch:before{content:'\f020'}.octicon-git-commit:before{content:'\f01f'}.octicon-git-compare:before{content:'\f0ac'}.octicon-git-merge:before{content:'\f023'}.octicon-git-pull-request-abandoned:before,.octicon-git-pull-request:before{content:'\f009'}.octicon-globe:before{content:'\f0b6'}.octicon-graph:before{content:'\f043'}.octicon-heart:before{content:'\2665'}.octicon-history:before{content:'\f07e'}.octicon-home:before{content:'\f08d'}.octicon-horizontal-rule:before{content:'\f070'}.octicon-hourglass:before{content:'\f09e'}.octicon-hubot:before{content:'\f09d'}.octicon-inbox:before{content:'\f0cf'}.octicon-info:before{content:'\f059'}.octicon-issue-closed:before{content:'\f028'}.octicon-issue-opened:before{content:'\f026'}.octicon-issue-reopened:before{content:'\f027'}.octicon-jersey:before{content:'\f019'}.octicon-jump-down:before{content:'\f072'}.octicon-jump-left:before{content:'\f0a5'}.octicon-jump-right:before{content:'\f0a6'}.octicon-jump-up:before{content:'\f073'}.octicon-key:before{content:'\f049'}.octicon-keyboard:before{content:'\f00d'}.octicon-law:before{content:'\f0d8'}.octicon-light-bulb:before{content:'\f000'}.octicon-link:before{content:'\f05c'}.octicon-link-external:before{content:'\f07f'}.octicon-list-ordered:before{content:'\f062'}.octicon-list-unordered:before{content:'\f061'}.octicon-location:before{content:'\f060'}.octicon-gist-private:before,.octicon-git-fork-private:before,.octicon-lock:before,.octicon-mirror-private:before{content:'\f06a'}.octicon-logo-github:before{content:'\f092'}.octicon-mail:before{content:'\f03b'}.octicon-mail-read:before{content:'\f03c'}.octicon-mail-reply:before{content:'\f051'}.octicon-mark-github:before{content:'\f00a'}.octicon-markdown:before{content:'\f0c9'}.octicon-megaphone:before{content:'\f077'}.octicon-mention:before{content:'\f0be'}.octicon-microscope:before{content:'\f089'}.octicon-milestone:before{content:'\f075'}.octicon-mirror-public:before,.octicon-mirror:before{content:'\f024'}.octicon-mortar-board:before{content:'\f0d7'}.octicon-move-down:before{content:'\f0a8'}.octicon-move-left:before{content:'\f074'}.octicon-move-right:before{content:'\f0a9'}.octicon-move-up:before{content:'\f0a7'}.octicon-mute:before{content:'\f080'}.octicon-no-newline:before{content:'\f09c'}.octicon-octoface:before{content:'\f008'}.octicon-organization:before{content:'\f037'}.octicon-package:before{content:'\f0c4'}.octicon-paintcan:before{content:'\f0d1'}.octicon-pencil:before{content:'\f058'}.octicon-person-add:before,.octicon-person-follow:before,.octicon-person:before{content:'\f018'}.octicon-pin:before{content:'\f041'}.octicon-playback-fast-forward:before{content:'\f0bd'}.octicon-playback-pause:before{content:'\f0bb'}.octicon-playback-play:before{content:'\f0bf'}.octicon-playback-rewind:before{content:'\f0bc'}.octicon-plug:before{content:'\f0d4'}.octicon-file-add:before,.octicon-file-directory-create:before,.octicon-gist-new:before,.octicon-plus:before,.octicon-repo-create:before{content:'\f05d'}.octicon-podium:before{content:'\f0af'}.octicon-primitive-dot:before{content:'\f052'}.octicon-primitive-square:before{content:'\f053'}.octicon-pulse:before{content:'\f085'}.octicon-puzzle:before{content:'\f0c0'}.octicon-question:before{content:'\f02c'}.octicon-quote:before{content:'\f063'}.octicon-radio-tower:before{content:'\f030'}.octicon-repo-delete:before,.octicon-repo:before{content:'\f001'}.octicon-repo-clone:before{content:'\f04c'}.octicon-repo-force-push:before{content:'\f04a'}.octicon-gist-fork:before,.octicon-repo-forked:before{content:'\f002'}.octicon-repo-pull:before{content:'\f006'}.octicon-repo-push:before{content:'\f005'}.octicon-rocket:before{content:'\f033'}.octicon-rss:before{content:'\f034'}.octicon-ruby:before{content:'\f047'}.octicon-screen-full:before{content:'\f066'}.octicon-screen-normal:before{content:'\f067'}.octicon-search-save:before,.octicon-search:before{content:'\f02e'}.octicon-server:before{content:'\f097'}.octicon-settings:before{content:'\f07c'}.octicon-log-in:before,.octicon-sign-in:before{content:'\f036'}.octicon-log-out:before,.octicon-sign-out:before{content:'\f032'}.octicon-split:before{content:'\f0c6'}.octicon-squirrel:before{content:'\f0b2'}.octicon-star-add:before,.octicon-star-delete:before,.octicon-star:before{content:'\f02a'}.octicon-steps:before{content:'\f0c7'}.octicon-stop:before{content:'\f08f'}.octicon-repo-sync:before,.octicon-sync:before{content:'\f087'}.octicon-tag-add:before,.octicon-tag-remove:before,.octicon-tag:before{content:'\f015'}.octicon-telescope:before{content:'\f088'}.octicon-terminal:before{content:'\f0c8'}.octicon-three-bars:before{content:'\f05e'}.octicon-thumbsdown:before{content:'\f0db'}.octicon-thumbsup:before{content:'\f0da'}.octicon-tools:before{content:'\f031'}.octicon-trashcan:before{content:'\f0d0'}.octicon-triangle-down:before{content:'\f05b'}.octicon-triangle-left:before{content:'\f044'}.octicon-triangle-right:before{content:'\f05a'}.octicon-triangle-up:before{content:'\f0aa'}.octicon-unfold:before{content:'\f039'}.octicon-unmute:before{content:'\f0ba'}.octicon-versions:before{content:'\f064'}.octicon-remove-close:before,.octicon-x:before{content:'\f081'}.octicon-zap:before{content:'\26A1'}body{font-family:'Helvetica Neue',Arial,Helvetica,sans-serif,'微软雅黑';background-color:#FAFAFA}img{border-radius:3px}.full.height{padding:0;margin:0 0 -87px 0;min-height:100%}.following.bar{z-index:900;left:0;width:100%;padding:.7em 0}.following.bar.light{background-color:#fff;border-bottom:1px solid #DDD;box-shadow:0 2px 3px rgba(0,0,0,.04)}.following.bar .ui.secondary.menu{height:30px}.following.bar .column .menu{margin-top:0}.following.bar .brand{float:left;margin-right:5px}.following.bar .head.link.item{padding-right:0!important}.following.bar .head.link.item .dropdown.icon,.following.bar .head.link.item .menu .octicon{margin-right:5px}.following.bar .user.avatar{padding:0;margin-top:1px}.following.bar .searchbox{background-color:#f4f4f4!important}.following.bar .searchbox:focus{background-color:#e9e9e9!important}.following.bar .octicon{width:16px;opacity:1!important;text-align:center}.ui.left{float:left}.ui.right{float:right}footer{margin-top:40px!important;background-color:#fff;border-top:1px solid #d6d6d6;clear:both;width:100%;color:#888}footer .fa{width:16px;text-align:center;color:#428bca}footer .ui.language.dropdown{z-index:10000}footer .links>*{border-left:1px solid #d6d6d6;padding-left:8px;margin-left:5px}footer .links>:first-child{border-left:none}.hide{display:none}.center{text-align:center}.text-error{color:#d95c5c!important}.img-1{width:2px;height:2px}.img-2{width:4px;height:4px}.img-3{width:6px;height:6px}.img-4{width:8px;height:8px}.img-5{width:10px;height:10px}.img-6{width:12px;height:12px}.img-7{width:14px;height:14px}.img-8{width:16px;height:16px}.img-9{width:18px;height:18px}.img-10{width:20px;height:20px}.img-11{width:22px;height:22px}.img-12{width:24px;height:24px}.img-13{width:26px;height:26px}.img-14{width:28px;height:28px}.img-15{width:30px;height:30px}.img-16{width:32px;height:32px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.home{padding-bottom:120px}.home .logo{max-width:250px}.home .hero h1,.home .hero h2{font-family:'PT Sans Narrow',sans-serif}.home .hero h1{font-size:7em}.home .hero h2{font-size:4em}.home .hero .octicon{color:#d9453d;font-size:60px;margin-right:10px}.home .hero.header{font-size:24px}.home p.large{font-size:20px}.home .stackable{padding-top:30px}.home a{color:#d9453d}.install{padding-top:45px;padding-bottom:120px}.install form label{text-align:right;width:40%!important}.install form input{width:35%!important}.install form .field{text-align:left}.install form .field .help{margin-left:41%}.install form .field.optional .title{margin-left:38%}.install .ui .checkbox{margin-left:40%!important}.install .ui .checkbox label{width:auto!important}.form .help{color:#999;padding-top:.6em;padding-bottom:.6em;display:inline-block}.ui.attached.header{background:#f0f0f0}.ui.attached.header .right{margin-top:-5px}.repository{padding-top:15px;padding-bottom:120px}.repository .head{height:75px;padding-top:20px;background-color:#FCFCFC}.repository .head .mega-octicon{width:30px}.repository .head .fork-flag,.repository .head a{font-weight:300}.repository .head .ui.label{margin-top:5px;vertical-align:top}.repository .head .fork-flag{margin-left:38px;display:block;font-size:11px;line-height:10px;white-space:nowrap}.repository .head .button{margin-left:10px}.repository .head .button i{margin-right:5px}.repository .head .num{font-weight:700}.repository .head .octicon{height:5px}.repository .navbar{height:60px;padding-top:20px}.repository .navbar .ui.secondary.menu .item{margin-left:-10px;margin-top:-7px}.repository .navbar .ui.secondary.menu .item>.input .color-picker,.repository .navbar .ui.secondary.menu .item>.input .new-label-input{background-color:#fff;border:1px solid rgba(0,0,0,.15)}.repository .navbar .ui.secondary.menu .item.input{margin-right:-7px}.repository .navbar .ui.secondary.menu .item .new-label-input{width:150px}.repository .navbar .ui.secondary.menu .item .color-picker{height:35px;width:auto;padding-left:30px}.repository .navbar .ui.secondary.menu .item .minicolors-swatch.minicolors-sprite{top:10px;left:10px;width:15px;height:15px}.repository .navbar .ui.secondary.menu .item.precolors{padding-left:0;padding-right:0;margin-right:10px;width:120px}.repository .navbar .ui.secondary.menu .item.precolors .color{float:left;width:15px;height:15px}.repository .filter.menu .label.color{margin-left:17px;padding:0 8px}.repository .filter.menu .octicon{float:left;margin-left:-5px;margin-right:-7px}.repository .filter.menu .menu{max-height:300px;overflow-x:auto;right:0!important;left:auto!important}.repository .filter.menu .menu .clickable .name{padding-left:15px!important}.repository .page.buttons{padding-top:15px}.repository .issue.list{clear:both;list-style:none}.repository .issue.list>.item{padding-top:15px;padding-bottom:10px;border-bottom:1px dashed #AAA}.repository .issue.list>.item .title{color:#444;font-size:15px;font-weight:700;margin:0 6px}.repository .issue.list>.item .title:hover{color:#000}.repository .issue.list>.item .comment{padding-right:10px;color:#666}.repository .issue.list>.item .desc{padding-top:5px;color:#999}.repository .issue.list>.item .desc a.milestone{padding-left:5px;color:#999!important}.repository .issue.list>.item .desc a.milestone:hover{color:#000!important}.repository .label.list{clear:both;list-style:none}.repository .label.list .item{padding-top:10px;padding-bottom:10px;border-bottom:1px dashed #AAA}.repository .label.list .item a{font-size:15px;padding-top:5px;padding-right:10px;color:#666}.repository .label.list .item a:hover{color:#000}.repository .label.list .item a.open-issues{margin-right:30px}.repository .milestone.list{clear:both;list-style:none}.repository .milestone.list>.item{padding-top:10px;padding-bottom:10px;border-bottom:1px dashed #AAA}.repository .milestone.list>.item>a{padding-top:5px;padding-right:10px;color:#000}.repository .milestone.list>.item>a:hover{color:#4078c0}.repository .milestone.list>.item .ui.progress{width:40%;padding:0;border:0;margin:0}.repository .milestone.list>.item .ui.progress .bar{height:20px}.repository .milestone.list>.item .meta{color:#999;padding-top:5px}.repository .milestone.list>.item .meta .issue-stats .octicon{padding-left:5px}.repository .milestone.list>.item .meta .overdue{color:red}.repository .milestone.list>.item .operate{margin-top:-15px}.repository .milestone.list>.item .operate>a{font-size:15px;padding-top:5px;padding-right:10px;color:#666}.repository .milestone.list>.item .operate>a:hover{color:#000}.repository .milestone.list>.item .content{padding-top:10px}.repository.new.milestone textarea{height:200px}.repository.settings .content{padding-left:20px!important}.settings .key.list .item:not(:first-child){border-top:1px solid #eaeaea}.settings .key.list .ssh-key-state-indicator{float:left;color:gray;padding-left:10px;padding-top:10px}.settings .key.list .ssh-key-state-indicator.active{color:#6cc644}.settings .key.list .meta{padding-top:5px}.settings .key.list .print{color:#767676}.settings .key.list .activity{color:#666}.edit-label.modal .color-picker{margin-top:-8px!important;height:35px;width:auto!important;padding-left:30px!important}.edit-label.modal .minicolors-swatch.minicolors-sprite{top:1px;left:10px;width:15px;height:15px}.edit-label.modal .precolors{margin-bottom:-11px!important;padding-left:0!important;padding-right:0!important;margin-right:10px!important;width:120px!important}.edit-label.modal .precolors .color{float:left;margin:0!important;width:15px;height:15px} \ No newline at end of file diff --git a/public/js/gogs.js b/public/js/gogs.js index 8802ea64..7e57a5e1 100644 --- a/public/js/gogs.js +++ b/public/js/gogs.js @@ -86,6 +86,13 @@ function initRepository() { return false; }); } + + // Settings + if ($('.repository.settings').length > 0) { + $('#add-deploy-key').click(function () { + $('#add-deploy-key-panel').show(); + }); + } }; $(document).ready(function () { diff --git a/public/less/_form.less b/public/less/_form.less index 3cc1c7f5..8b2c30b1 100644 --- a/public/less/_form.less +++ b/public/less/_form.less @@ -5,4 +5,10 @@ padding-bottom: .6em; display: inline-block; } +} +.ui.attached.header { + background: #f0f0f0; + .right { + margin-top: -5px; + } } \ No newline at end of file diff --git a/public/less/_install.less b/public/less/_install.less index 244f7c0d..ffc53252 100644 --- a/public/less/_install.less +++ b/public/less/_install.less @@ -1,9 +1,6 @@ .install { padding-top: 45px; padding-bottom: @footer-margin * 3; - .attached.header { - background: #f0f0f0; - } form { label { text-align: right; diff --git a/public/less/_repository.less b/public/less/_repository.less index db245e93..bdea35c0 100644 --- a/public/less/_repository.less +++ b/public/less/_repository.less @@ -217,6 +217,36 @@ height: 200px; } } + + &.settings { + .content { + padding-left: 20px!important; + } + } +} + +.settings .key.list { + .item:not(:first-child) { + border-top: 1px solid #eaeaea; + } + .ssh-key-state-indicator { + float: left; + color: gray; + padding-left: 10px; + padding-top: 10px; + &.active { + color: #6cc644; + } + } + .meta { + padding-top: 5px; + } + .print { + color: #767676; + } + .activity { + color: #666; + } } .edit-label.modal { diff --git a/routers/repo/setting.go b/routers/repo/setting.go index 12fc428c..8f6ef178 100644 --- a/routers/repo/setting.go +++ b/routers/repo/setting.go @@ -27,10 +27,11 @@ const ( SETTINGS_OPTIONS base.TplName = "repo/settings/options" COLLABORATION base.TplName = "repo/settings/collaboration" HOOKS base.TplName = "repo/settings/hooks" - GITHOOKS base.TplName = "repo/settings/githooks" - GITHOOK_EDIT base.TplName = "repo/settings/githook_edit" HOOK_NEW base.TplName = "repo/settings/hook_new" ORG_HOOK_NEW base.TplName = "org/settings/hook_new" + GITHOOKS base.TplName = "repo/settings/githooks" + GITHOOK_EDIT base.TplName = "repo/settings/githook_edit" + DEPLOY_KEYS base.TplName = "repo/settings/deploy_keys" ) func Settings(ctx *middleware.Context) { @@ -584,6 +585,10 @@ func getOrgRepoCtx(ctx *middleware.Context) (*OrgRepoCtx, error) { } } +func TriggerHook(ctx *middleware.Context) { + models.HookQueue.AddRepoID(ctx.Repo.Repository.Id) +} + func GitHooks(ctx *middleware.Context) { ctx.Data["Title"] = ctx.Tr("repo.settings") ctx.Data["PageIsSettingsGitHooks"] = true @@ -635,6 +640,70 @@ func GitHooksEditPost(ctx *middleware.Context) { ctx.Redirect(ctx.Repo.RepoLink + "/settings/hooks/git") } -func TriggerHook(ctx *middleware.Context) { - models.HookQueue.AddRepoID(ctx.Repo.Repository.Id) +func SettingsDeployKeys(ctx *middleware.Context) { + ctx.Data["Title"] = ctx.Tr("repo.settings") + ctx.Data["PageIsSettingsKeys"] = true + + keys, err := models.ListDeployKeys(ctx.Repo.Repository.Id) + if err != nil { + ctx.Handle(500, "ListDeployKeys", err) + return + } + ctx.Data["Deploykeys"] = keys + + ctx.HTML(200, DEPLOY_KEYS) +} + +func SettingsDeployKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { + ctx.Data["Title"] = ctx.Tr("repo.settings") + ctx.Data["PageIsSettingsKeys"] = true + + if ctx.HasError() { + ctx.HTML(200, DEPLOY_KEYS) + return + } + + content, err := models.CheckPublicKeyString(form.Content) + if err != nil { + if err == models.ErrKeyUnableVerify { + ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key")) + } else { + ctx.Data["HasError"] = true + ctx.Data["Err_Content"] = true + ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error())) + ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys") + return + } + } + + if err = models.AddDeployKey(ctx.Repo.Repository.Id, form.Title, content); err != nil { + ctx.Data["HasError"] = true + switch { + case models.IsErrKeyAlreadyExist(err): + ctx.Data["Err_Content"] = true + ctx.RenderWithErr(ctx.Tr("repo.settings.key_been_used"), DEPLOY_KEYS, &form) + case models.IsErrKeyNameAlreadyUsed(err): + ctx.Data["Err_Title"] = true + ctx.RenderWithErr(ctx.Tr("repo.settings.key_name_used"), DEPLOY_KEYS, &form) + default: + ctx.Handle(500, "AddDeployKey", err) + } + return + } + + log.Trace("Deploy key added: %d", ctx.Repo.Repository.Id) + ctx.Flash.Success(ctx.Tr("repo.settings.add_key_success", form.Title)) + ctx.Redirect(ctx.Repo.RepoLink + "/settings/keys") +} + +func DeleteDeployKey(ctx *middleware.Context) { + if err := models.DeleteDeployKey(ctx.QueryInt64("id")); err != nil { + ctx.Flash.Error("DeleteDeployKey: " + err.Error()) + } else { + ctx.Flash.Success(ctx.Tr("repo.settings.deploy_key_deletion_success")) + } + + ctx.JSON(200, map[string]interface{}{ + "redirect": ctx.Repo.RepoLink + "/settings/keys", + }) } diff --git a/routers/user/setting.go b/routers/user/setting.go index b31e93a6..de9af655 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -305,7 +305,7 @@ func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { return } - if err = models.DeletePublicKey(&models.PublicKey{Id: id}); err != nil { + if err = models.DeletePublicKey(&models.PublicKey{ID: id}); err != nil { ctx.Handle(500, "DeletePublicKey", err) } else { log.Trace("SSH key deleted: %s", ctx.User.Name) @@ -321,15 +321,8 @@ func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { return } - // Parse openssh style string from form content - content, err := models.ParseKeyString(form.Content) + content, err := models.CheckPublicKeyString(form.Content) if err != nil { - ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error())) - ctx.Redirect(setting.AppSubUrl + "/user/settings/ssh") - return - } - - if ok, err := models.CheckPublicKeyString(content); !ok { if err == models.ErrKeyUnableVerify { ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key")) } else { @@ -339,21 +332,19 @@ func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { } } - k := &models.PublicKey{ - OwnerId: ctx.User.Id, - Name: form.SSHTitle, - Content: content, - } - if err := models.AddPublicKey(k); err != nil { - if err == models.ErrKeyAlreadyExist { - ctx.RenderWithErr(ctx.Tr("form.ssh_key_been_used"), SETTINGS_SSH_KEYS, &form) - return + if err = models.AddPublicKey(ctx.User.Id, form.Title, content); err != nil { + switch { + case models.IsErrKeyAlreadyExist(err): + ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), SETTINGS_SSH_KEYS, &form) + case models.IsErrKeyNameAlreadyUsed(err): + ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), SETTINGS_SSH_KEYS, &form) + default: + ctx.Handle(500, "AddPublicKey", err) } - ctx.Handle(500, "ssh.AddPublicKey", err) return } else { log.Trace("SSH key added: %s", ctx.User.Name) - ctx.Flash.Success(ctx.Tr("settings.add_key_success")) + ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title)) ctx.Redirect(setting.AppSubUrl + "/user/settings/ssh") return } diff --git a/templates/.VERSION b/templates/.VERSION index b7559a24..8a54eae6 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.6.4.0805 Beta \ No newline at end of file +0.6.4.0806 Beta \ No newline at end of file diff --git a/templates/base/alert.tmpl b/templates/base/alert.tmpl index c845e36d..e71be803 100644 --- a/templates/base/alert.tmpl +++ b/templates/base/alert.tmpl @@ -7,4 +7,9 @@

{{.Flash.SuccessMsg}}

+{{end}} +{{if .Flash.InfoMsg}} +
+

{{.Flash.InfoMsg}}

+
{{end}} \ No newline at end of file diff --git a/templates/repo/settings/deploy_keys.tmpl b/templates/repo/settings/deploy_keys.tmpl new file mode 100644 index 00000000..bed39a73 --- /dev/null +++ b/templates/repo/settings/deploy_keys.tmpl @@ -0,0 +1,97 @@ +{{template "base/head" .}} +
+ {{template "repo/header" .}} +
+ {{template "repo/settings/navbar" .}} +
+ {{template "base/alert" .}} +

+ {{.i18n.Tr "repo.settings.deploy_keys"}} +
+
{{.i18n.Tr "repo.settings.add_deploy_key"}}
+
+

+
+ {{if .Deploykeys}} +
+ {{range .Deploykeys}} +
+
+ +
+
+ +
+
+ {{.Name}} +
+ {{.Fingerprint}} +
+
+ {{$.i18n.Tr "settings.add_on"}} {{DateFmtShort .Created}} {{if .HasUsed}}{{$.i18n.Tr "settings.last_used"}} {{DateFmtShort .Updated}}{{else}}{{$.i18n.Tr "settings.no_activity"}}{{end}} +
+
+
+ +
+
+ {{end}} +
+ {{else}} + {{.i18n.Tr "repo.settings.no_deploy_keys"}} + {{end}} +
+
+
+

+ {{.i18n.Tr "repo.settings.add_deploy_key"}} +

+
+
+ {{.CsrfTokenHtml}} +
+ + +
+
+ + +
+ +
+
+
+
+
+
+ + +{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/repo/settings/nav.tmpl b/templates/repo/settings/nav.tmpl index 6803c563..06bad968 100644 --- a/templates/repo/settings/nav.tmpl +++ b/templates/repo/settings/nav.tmpl @@ -8,7 +8,7 @@ {{if or .SignedUser.AllowGitHook .SignedUser.IsAdmin}}
  • {{.i18n.Tr "repo.settings.githooks"}}
  • {{end}} - +
  • {{.i18n.Tr "repo.settings.deploy_keys"}}
  • \ No newline at end of file diff --git a/templates/repo/settings/navbar.tmpl b/templates/repo/settings/navbar.tmpl new file mode 100644 index 00000000..cf27980f --- /dev/null +++ b/templates/repo/settings/navbar.tmpl @@ -0,0 +1,19 @@ + \ No newline at end of file diff --git a/templates/user/settings/sshkeys.tmpl b/templates/user/settings/sshkeys.tmpl index 42b76039..995e6425 100644 --- a/templates/user/settings/sshkeys.tmpl +++ b/templates/user/settings/sshkeys.tmpl @@ -28,7 +28,7 @@
    {{$.CsrfTokenHtml}} - +
    -- cgit v1.2.3 From d922b7e5049a88fbba436ad08c817ac79ee64c6b Mon Sep 17 00:00:00 2001 From: Unknwon Date: Fri, 7 Aug 2015 00:00:11 +0800 Subject: #1443 set first user to be admin ...not just ID=1 --- models/user.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'models/user.go') diff --git a/models/user.go b/models/user.go index 1e514cdf..37e7640e 100644 --- a/models/user.go +++ b/models/user.go @@ -314,19 +314,23 @@ func CreateUser(u *User) (err error) { return err } - // Auto-set admin for user whose ID is 1. - if u.Id == 1 { + // Auto-set admin for the first user. + if countUsers(sess) == 1 { u.IsAdmin = true u.IsActive = true - _, err = x.Id(u.Id).UseBool().Update(u) + _, err = x.Id(u.Id).AllCols().Update(u) } return err } +func countUsers(e Engine) int64 { + count, _ := e.Where("type=0").Count(new(User)) + return count +} + // CountUsers returns number of users. func CountUsers() int64 { - count, _ := x.Where("type=0").Count(new(User)) - return count + return countUsers(x) } // GetUsers returns given number of user objects with offset. -- cgit v1.2.3 From b1f08d3218cd83ae854fbfe98a39b6d2f0fa47e3 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Fri, 7 Aug 2015 00:09:28 +0800 Subject: more on #1443 --- models/user.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'models/user.go') diff --git a/models/user.go b/models/user.go index 37e7640e..6dd31536 100644 --- a/models/user.go +++ b/models/user.go @@ -315,7 +315,7 @@ func CreateUser(u *User) (err error) { } // Auto-set admin for the first user. - if countUsers(sess) == 1 { + if CountUsers() == 1 { u.IsAdmin = true u.IsActive = true _, err = x.Id(u.Id).AllCols().Update(u) -- cgit v1.2.3