| @@ -1236,6 +1236,10 @@ editor.cannot_commit_to_protected_branch = Cannot commit to protected branch '%s | |||
| editor.no_commit_to_branch = Unable to commit directly to branch because: | |||
| editor.user_no_push_to_branch = User cannot push to branch | |||
| editor.require_signed_commit = Branch requires a signed commit | |||
| editor.repo_too_large = Repository can not exceed %d MB | |||
| editor.repo_file_invalid = Upload files are invalid | |||
| editor.upload_file_too_much = Can not upload more than %d files at a time | |||
| commits.desc = Browse source code change history. | |||
| commits.commits = Commits | |||
| @@ -1244,6 +1244,9 @@ editor.cannot_commit_to_protected_branch=不可以提交到受保护的分支 '% | |||
| editor.no_commit_to_branch=无法直接提交分支,因为: | |||
| editor.user_no_push_to_branch=用户不能推送到分支 | |||
| editor.require_signed_commit=分支需要签名提交 | |||
| editor.repo_too_large = 代码仓总大小不能超过%dMB | |||
| editor.repo_file_invalid = 提交的文件非法 | |||
| editor.upload_file_too_much = 不能同时提交超过%d个文件 | |||
| commits.desc=浏览代码修改历史 | |||
| commits.commits=次代码提交 | |||
| @@ -616,8 +616,15 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) { | |||
| } | |||
| if err := repo_service.CheckRepoSizeLimit(ctx.Repo.Repository, form.Files); err != nil { | |||
| //ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", part), tplUploadFile, &form) | |||
| ctx.RenderWithErr(err.Error(), tplUploadFile, &form) | |||
| if repo_service.IsRepoTooLargeErr(err) { | |||
| ctx.RenderWithErr(ctx.Tr("repo.editor.repo_too_large", setting.Repository.RepoMaxSize), tplUploadFile, &form) | |||
| } else if repo_service.IsUploadFileInvalidErr(err) { | |||
| ctx.RenderWithErr(ctx.Tr("repo.editor.repo_file_invalid"), tplUploadFile, &form) | |||
| } else if repo_service.IsUploadFileTooMuchErr(err) { | |||
| ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_too_much", setting.Repository.Upload.MaxFiles), tplUploadFile, &form) | |||
| } else { | |||
| ctx.RenderWithErr(err.Error(), tplUploadFile, &form) | |||
| } | |||
| return | |||
| } | |||
| @@ -365,8 +365,7 @@ func HTTP(ctx *context.Context) { | |||
| ctx.NotFound("Smart Git HTTP", err) | |||
| return | |||
| } | |||
| route.handler(serviceHandler{cfg, w, r, dir, file, cfg.Env}) | |||
| route.handler(serviceHandler{cfg, w, r, dir, file, cfg.Env, repo}) | |||
| return | |||
| } | |||
| } | |||
| @@ -429,6 +428,7 @@ type serviceHandler struct { | |||
| dir string | |||
| file string | |||
| environ []string | |||
| repo *models.Repository | |||
| } | |||
| func (h *serviceHandler) setHeaderNoCache() { | |||
| @@ -546,6 +546,19 @@ func serviceRPC(h serviceHandler, service string) { | |||
| return | |||
| } | |||
| } | |||
| content, _ := ioutil.ReadAll(reqBody) | |||
| //check size | |||
| if service == "receive-pack" { | |||
| if err := repo_service.CheckRepoTotalSizeLimit(h.repo, int64(len(content))); err != nil { | |||
| h.w.WriteHeader(http.StatusOK) | |||
| str := GenerateGitErrorBody(err.Error()) | |||
| h.w.Write([]byte(str)) | |||
| if h.w.Header().Get("Content-Type") == "" { | |||
| h.w.Header().Set("Content-Type", "application/x-git-receive-pack-result") | |||
| } | |||
| return | |||
| } | |||
| } | |||
| // set this for allow pre-receive and post-receive execute | |||
| h.environ = append(h.environ, "SSH_ORIGINAL_COMMAND="+service) | |||
| @@ -560,7 +573,7 @@ func serviceRPC(h serviceHandler, service string) { | |||
| } | |||
| cmd.Stdout = h.w | |||
| cmd.Stdin = reqBody | |||
| cmd.Stdin = bytes.NewReader(content) | |||
| cmd.Stderr = &stderr | |||
| pid := process.GetManager().Add(fmt.Sprintf("%s %s %s [repo_path: %s]", git.GitExecutable, service, "--stateless-rpc", h.dir), cancel) | |||
| @@ -572,6 +585,39 @@ func serviceRPC(h serviceHandler, service string) { | |||
| } | |||
| } | |||
| func GenerateGitErrorBody(content string) string { | |||
| var builder strings.Builder | |||
| builder.WriteString(GenerateErrStartPKTLine()) | |||
| builder.WriteString(GeneratePKTLine(content)) | |||
| builder.WriteString(GenerateEndPKTLine()) | |||
| return builder.String() | |||
| } | |||
| func GeneratePKTLine(content string) string { | |||
| content = "\u0002\033[31m " + content + " \033[0m" | |||
| l := len(content) | |||
| prefixLength := 4 | |||
| suffix := "\n" | |||
| f := strconv.FormatInt(int64(l+prefixLength+len(suffix)), 16) | |||
| lf := len(f) | |||
| if lf == 1 { | |||
| f = "000" + f | |||
| } else if lf == 2 { | |||
| f = "00" + f | |||
| } else if lf == 3 { | |||
| f = "0" + f | |||
| } | |||
| return f + content + suffix | |||
| } | |||
| func GenerateEndPKTLine() string { | |||
| return "0000" | |||
| } | |||
| func GenerateErrStartPKTLine() string { | |||
| return "0031\u0001000eunpack err\n0019ok refs/heads/master\n0000" | |||
| } | |||
| func serviceUploadPack(h serviceHandler) { | |||
| serviceRPC(h, "upload-pack") | |||
| } | |||
| @@ -5,7 +5,6 @@ | |||
| package repository | |||
| import ( | |||
| "errors" | |||
| "fmt" | |||
| "io/ioutil" | |||
| "net/http" | |||
| @@ -181,7 +180,7 @@ func CheckRepoSizeLimit(repo *models.Repository, fileIds []string) error { | |||
| } | |||
| totalSize, err := CountUploadFileSizeByIds(fileIds) | |||
| if err != nil { | |||
| return errors.New("upload files are invalid") | |||
| return UploadFileInvalidErr{} | |||
| } | |||
| if err := CheckRepoTotalSizeLimit(repo, totalSize); err != nil { | |||
| return err | |||
| @@ -191,14 +190,14 @@ func CheckRepoSizeLimit(repo *models.Repository, fileIds []string) error { | |||
| func CheckRepoTotalSizeLimit(repo *models.Repository, uploadFileSize int64) error { | |||
| if repo.Size+uploadFileSize > setting.Repository.RepoMaxSize*1024*1024 { | |||
| return errors.New(fmt.Sprintf("repository can not exceed %d MB", setting.Repository.RepoMaxSize)) | |||
| return RepoTooLargeErr{} | |||
| } | |||
| return nil | |||
| } | |||
| func CheckRepoNumOnceLimit(uploadFileNum int) error { | |||
| if uploadFileNum > setting.Repository.Upload.MaxFiles { | |||
| return errors.New(fmt.Sprintf("can not upload more than %d files at a time", setting.Repository.Upload.MaxFiles)) | |||
| return UploadFileTooMuchErr{} | |||
| } | |||
| return nil | |||
| } | |||
| @@ -231,3 +230,51 @@ func GetUploadFileSize(upload *models.Upload) (int64, error) { | |||
| return info.Size(), nil | |||
| } | |||
| type RepoTooLargeErr struct { | |||
| } | |||
| func (RepoTooLargeErr) Error() string { | |||
| return fmt.Sprintf("Repository can not exceed %d MB. Please remove some unnecessary files and try again", setting.Repository.RepoMaxSize) | |||
| } | |||
| func IsRepoTooLargeErr(err error) bool { | |||
| _, ok := err.(RepoTooLargeErr) | |||
| return ok | |||
| } | |||
| type RepoFileTooLargeErr struct { | |||
| } | |||
| func (RepoFileTooLargeErr) Error() string { | |||
| return "repository file is too large" | |||
| } | |||
| func IsRepoFileTooLargeErr(err error) bool { | |||
| _, ok := err.(RepoFileTooLargeErr) | |||
| return ok | |||
| } | |||
| type UploadFileTooMuchErr struct { | |||
| } | |||
| func (UploadFileTooMuchErr) Error() string { | |||
| return "upload files are too lmuch" | |||
| } | |||
| func IsUploadFileTooMuchErr(err error) bool { | |||
| _, ok := err.(UploadFileTooMuchErr) | |||
| return ok | |||
| } | |||
| type UploadFileInvalidErr struct { | |||
| } | |||
| func (UploadFileInvalidErr) Error() string { | |||
| return "upload files are invalid" | |||
| } | |||
| func IsUploadFileInvalidErr(err error) bool { | |||
| _, ok := err.(UploadFileInvalidErr) | |||
| return ok | |||
| } | |||