Reject Badly Formatted Patch Files

This Patch Does Not Apply To The Current Repository
Sarah@auth.lopeos.org submitted a patch request Feb 15, 2025 22:50
  • Title: Error When Rejecting Badly Formatted Patch Files / Non Patch Files
  • Author: Sarah Jamie Lewis <sarah@openprivacy.ca>

repo/requests.go

@@ -24,6 +24,7 @@ type RequestList struct {
  	User     common.AuthInfo

              	Repo     string

              	Requests []*common.IssueRequest

            +	Warnings []Warning

              }

              

              type RequestManager struct {

            
@@ -60,6 +61,11 @@ func NewRequestManager(config *common.Config, repo string, ac *auth.AuthClient)
  	return &RequestManager{config: config, repo: repo, ac: ac, patchHandler: *NewPatchHandler(config, repo)}

              }

              

            +func (rm *RequestManager) errorHandler(err string, w http.ResponseWriter, r *http.Request) {

            +	r.AddCookie(&http.Cookie{Name: "error", Value: err})

            +	rm.Serve(w, r)

            +}

            +

              func (rm *RequestManager) ApplyPatch(w http.ResponseWriter, r *http.Request) {

              

              	authUser := rm.ac.GetAuthInfo(rm.config, r)

            
@@ -102,13 +108,19 @@ func (rm *RequestManager) ServePatch(w http.ResponseWriter, r *http.Request) {
  

              func (rm *RequestManager) Serve(w http.ResponseWriter, r *http.Request) {

              

            +	baseResponse := RequestList{Repo: rm.repo, User: rm.ac.GetAuthInfo(rm.config, r)}

            +

            +	if cookie, _ := r.Cookie("error"); cookie != nil {

            +		baseResponse.Warnings = append(baseResponse.Warnings, Warning{Level: WARN, Message: cookie.Value})

            +	}

            +

              	if strings.HasSuffix(r.URL.Path, "/new") {

              		if value := r.FormValue("type"); value == "issue" {

            -			rm.config.Templates.ExecuteTemplate(w, "request.new.tpl.html", RequestList{Repo: rm.repo, User: rm.ac.GetAuthInfo(rm.config, r)})

            +			rm.config.Templates.ExecuteTemplate(w, "request.new.tpl.html", baseResponse)

              			return

              		}

              		if value := r.FormValue("type"); value == "patch" {

            -			rm.config.Templates.ExecuteTemplate(w, "request.newpatch.tpl.html", RequestList{Repo: rm.repo, User: rm.ac.GetAuthInfo(rm.config, r)})

            +			rm.config.Templates.ExecuteTemplate(w, "request.newpatch.tpl.html", baseResponse)

              			return

              		}

              	}

            
@@ -121,7 +133,7 @@ func (rm *RequestManager) Serve(w http.ResponseWriter, r *http.Request) {
  	// list all issues

              	if strings.HasSuffix(r.URL.Path, "requests/") {

              		authuser := rm.ac.GetAuthInfo(rm.config, r)

            -		rl := RequestList{Repo: rm.repo, User: authuser}

            +		rl := baseResponse

              

              		// Get a list of issues in creation order...

              		issueList := rm.LoadIssues(rm.RequestLogPath(), func(hash string) (*common.IssueRequest, error) {

            
@@ -152,7 +164,7 @@ func (rm *RequestManager) Serve(w http.ResponseWriter, r *http.Request) {
  	// otherwise list a single issue...

              	authuser := rm.ac.GetAuthInfo(rm.config, r)

              	// otherwise...

            -	rt := RequestThread{Repo: rm.repo, User: rm.ac.GetAuthInfo(rm.config, r)}

            +	rt := RequestThread{User: baseResponse.User, Repo: baseResponse.Repo, Warnings: baseResponse.Warnings}

              	issuehash := path.Base(r.URL.Path)

              	// Get a list of issues in creation order...

              

            
@@ -369,6 +381,7 @@ func (rm *RequestManager) updateLog(logpath string, hash string, status common.L
  }

              

              func (rm *RequestManager) handlePatch(w http.ResponseWriter, r *http.Request) {

            +

              	// Parse our multipart form, 10 << 20 specifies a maximum

              	// upload of 10 MB files.

              	r.ParseMultipartForm(1024 * 1024 * 200)

            
@@ -377,20 +390,20 @@ func (rm *RequestManager) handlePatch(w http.ResponseWriter, r *http.Request) {
  	// the Header and the size of the file

              	file, _, err := r.FormFile("patchfile")

              	if err != nil {

            -		http.Error(w, err.Error(), http.StatusBadRequest)

            +		rm.errorHandler("Could Not Create Patch Request", w, r)

              		return

              	}

              	defer file.Close()

              

              	id, err := common.RandomIdent()

              	if err != nil {

            -		http.Error(w, err.Error(), http.StatusBadRequest)

            +		rm.errorHandler("Could Not Create Patch Request", w, r)

              		return

              	}

              

              	fileBytes, err := io.ReadAll(file)

              	if err != nil {

            -		http.Error(w, err.Error(), http.StatusBadRequest)

            +		rm.errorHandler("Could Not Create Patch Request", w, r)

              		return

              	}

              

            
@@ -398,14 +411,18 @@ func (rm *RequestManager) handlePatch(w http.ResponseWriter, r *http.Request) {
  	buf := bytes.NewBuffer(fileBytes)

              	_, description, err := gitdiff.Parse(buf)

              	if err != nil {

            -		http.Error(w, err.Error(), http.StatusBadRequest)

            +		rm.errorHandler("Could Not Create Patch Request", w, r)

            +		return

            +	}

            +	if _, err := gitdiff.ParsePatchHeader(description); err != nil {

            +		rm.errorHandler("Could Not Create Patch Request", w, r)

              		return

              	}

              

              	summary := r.FormValue("summary")

              	issueRequest, err := common.NewIssueRequest(summary, description, rm.ac.GetAuthInfo(rm.config, r))

              	if err != nil {

            -		http.Error(w, err.Error(), http.StatusBadRequest)

            +		rm.errorHandler("Could Not Create Patch Request", w, r)

              		return

              	}

              	issueRequest.PatchRef = id

            
@@ -458,6 +475,11 @@ func (rm *RequestManager) SaveIssue(issueRequest *common.IssueRequest, w http.Re
  }

              

              func (rm *RequestManager) handleNew(w http.ResponseWriter, r *http.Request) {

            +	if r.Response != nil {

            +		fmt.Printf("now here....\n")

            +		rm.Serve(w, r)

            +		return

            +	}

              

              	summary := r.FormValue("summary")

              	description := r.FormValue("description")

            

senary.go

@@ -135,6 +135,8 @@ func main() {
  				http.HandleFunc("POST "+path.Join("/repos/", e.Name(), "requests")+"/new", rm.Submit)

              				http.HandleFunc("POST "+path.Join("/repos/", e.Name(), "requests")+"/approve", rm.Submit)

              				http.HandleFunc("POST "+path.Join("/repos/", e.Name(), "requests")+"/tombstone", rm.Submit)

            +

            +				// allow downloading patches and applying them...

              				http.HandleFunc("GET "+path.Join("/repos/", e.Name(), "patch/{id}/{patch}")+"/{$}", rm.ServePatch)

              				http.HandleFunc("POST "+path.Join("/repos/", e.Name(), "apply/{id}/{patch}")+"/{$}", rm.ApplyPatch)

              				// allow https cloning by redirecting to git https backend

            

static/css/custom.css

@@ -72,4 +72,10 @@ mark.warning {
  

              mark.info {

                background-color:var(--pico-color-jade-600);color:var(--pico-color-light);

            +}

            +

            +.error {

            +  background-color:var(--pico-color-pink-600);color:var(--pico-color-light);

            +  font-weight: bold;

            +  text-align: center;

              }
            

templates/request.newpatch.tpl.html

@@ -10,6 +10,12 @@
  

              {{template "repomenu.tpl.html" .}}

              <div>

            +

            +  {{range .Warnings}}

            +      <div class="error">{{.Message}}</div>

            +      <br/>

            +  {{end}}

            +

                <h2>Submit a New Change Request</h2>

              <form method="post" enctype="multipart/form-data" >

                <fieldset>