From 20ece60a72d3591bcbb1332426016226aada0ff1 Mon Sep 17 00:00:00 2001
From: Dane Everitt <dane@daneeveritt.com>
Date: Sun, 8 Nov 2020 17:06:40 -0800
Subject: [PATCH] Fix files not being editable correctly in the panel; closes
 pterodactyl/panel#2679

---
 CHANGELOG.md                  |  4 ++++
 router/router_server_files.go | 29 +++++++++++++++++++----------
 2 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 47199d1c..d63d5e67 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## v1.1.1
+### Fixed
+* Fixes certain files returning invalid data in the request due to a bad header set after sending data down the line.
+
 ## v1.1.0
 This release **requires** `Panel@1.1.0` or later to run due to API changes.
 
diff --git a/router/router_server_files.go b/router/router_server_files.go
index 07e1d434..d7ad3469 100644
--- a/router/router_server_files.go
+++ b/router/router_server_files.go
@@ -35,19 +35,28 @@ func getServerFileContents(c *gin.Context) {
 		return
 	}
 
+	c.Header("X-Mime-Type", st.Mimetype)
+	c.Header("Content-Length", strconv.Itoa(int(st.Info.Size())))
+
+	// If a download parameter is included in the URL go ahead and attach the necessary headers
+	// so that the file can be downloaded.
+	if c.Query("download") != "" {
+		c.Header("Content-Disposition", "attachment; filename="+st.Info.Name())
+		c.Header("Content-Type", "application/octet-stream")
+	}
+
+	// TODO(dane): should probably come up with a different approach here. If an error is encountered
+	//  by this Readfile call you'll end up causing a (recovered) panic in the program because so many
+	//  headers have already been set. We should probably add a RawReadfile that just returns the file
+	//  to be read and then we can stream from that safely without error.
+	//
+	// Until that becomes a problem though I'm just going to leave this how it is. The panic is recovered
+	// and a normal 500 error is returned to the client to my knowledge. It is also very unlikely to
+	// happen since we're doing so much before this point that would normally throw an error if there
+	// was a problem with the file.
 	if err := s.Filesystem().Readfile(p, c.Writer); err != nil {
 		TrackedServerError(err, s).AbortFilesystemError(c)
 		return
-	} else {
-		c.Header("X-Mime-Type", st.Mimetype)
-		c.Header("Content-Length", strconv.Itoa(int(st.Info.Size())))
-
-		// If a download parameter is included in the URL go ahead and attach the necessary headers
-		// so that the file can be downloaded.
-		if c.Query("download") != "" {
-			c.Header("Content-Disposition", "attachment; filename="+st.Info.Name())
-			c.Header("Content-Type", "application/octet-stream")
-		}
 	}
 }