mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Fix serving of raw wiki files other than .md (#5814)
* Fix serving of raw wiki files other than .md Closes #4690. Closes #4395. Signed-off-by: Gabriel Silva Simões <simoes.sgabriel@gmail.com> * Simplify code at routers/repo/wiki.go Signed-off-by: Gabriel Silva Simões <simoes.sgabriel@gmail.com> * Add more files to user2/repo1.wiki for testing Signed-off-by: Gabriel Silva Simões <simoes.sgabriel@gmail.com> * Update macaron to v1.3.2 Signed-off-by: Gabriel Silva Simões <simoes.sgabriel@gmail.com> * Add tests for WikiRaw Signed-off-by: Gabriel Silva Simões <simoes.sgabriel@gmail.com> * Fix NewResponseWriter usage due to macaron update Signed-off-by: Gabriel Silva Simões <simoes.sgabriel@gmail.com> * Add raw to reserved wiki names Signed-off-by: Gabriel Silva Simões <simoes.sgabriel@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						techknowlogick
					
				
			
			
				
	
			
			
			
						parent
						
							4a747aef7b
						
					
				
				
					commit
					3b7f41f9f7
				
			
							
								
								
									
										6
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							@@ -1108,12 +1108,12 @@
 | 
				
			|||||||
  version = "v2.5.1"
 | 
					  version = "v2.5.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[projects]]
 | 
					[[projects]]
 | 
				
			||||||
  digest = "1:cfe1730a152ff033ad7d9c115d22e36b19eec6d5928c06146b9119be45d39dc0"
 | 
					  digest = "1:de2e7294c9bd0b7d07ada8e98ad02cbbaabacff90eedebe7454ebdbab50d0d19"
 | 
				
			||||||
  name = "gopkg.in/macaron.v1"
 | 
					  name = "gopkg.in/macaron.v1"
 | 
				
			||||||
  packages = ["."]
 | 
					  packages = ["."]
 | 
				
			||||||
  pruneopts = "NUT"
 | 
					  pruneopts = "NUT"
 | 
				
			||||||
  revision = "75f2e9b42e99652f0d82b28ccb73648f44615faa"
 | 
					  revision = "dfcb80ca86e8534962c62812efd93209c7e600e7"
 | 
				
			||||||
  version = "v1.2.4"
 | 
					  version = "v1.3.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[projects]]
 | 
					[[projects]]
 | 
				
			||||||
  digest = "1:00126f697efdcab42f07c89ac8bf0095fb2328aef6464e070055154088cea859"
 | 
					  digest = "1:00126f697efdcab42f07c89ac8bf0095fb2328aef6464e070055154088cea859"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					x<01><><EFBFBD>m<EFBFBD> D<>M<15><>Y<EFBFBD><59><1A><>(<28>J<01>`<60>5<EFBFBD>ɜ-<2D>K*Ki,Hi!?<3F><><<3C>i<EFBFBD>Vki0Z<30><5A>XH<58>D(Z6ĨG<C4A8>Sb<53><62>3<EFBFBD>JD<4A>h<EFBFBD><68>!<21>uB<1D><>DaJp<>	<09><><02><>F<EFBFBD>Lƹ4+~<7E><>v<EFBFBD>;<3B><><EFBFBD>
 | 
				
			||||||
 | 
					e<><65><EFBFBD><EFBFBD><EFBFBD>[Nx>K<><4B><1C><><EFBFBD>_s<5F><73>q<>/<2F>]09MHpѤ<70><D1A4>k<EFBFBD><6B><EFBFBD>_d<5F>-%<25>풇۞<ED9287><DB9E>	v<>_<>]<5D><>^<5E>/<2F>I[t
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					x<15>M<0E>@<0C><><EFBFBD>M<><19><17><08>r<EFBFBD><EFBFBD>6<EFBFBD><36>&&&<26><>9Le<4C>św<C59B><77><EFBFBD><EFBFBD>t<#<23><><EFBFBD>͡<>mv-<2D><>0w<30>b<EFBFBD><62>jy̖<79><CC96>ڗ~[<5B><><EFBFBD><EFBFBD><EFBFBD>=H<15><0C>.<2E>"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǁ=
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					x<01><><EFBFBD>m<EFBFBD>0<10><><EFBFBD>)n<><06><>t2<14>S<07><04><><EFBFBD>`ņ<><C586><EFBFBD>e<EFBFBD>,VY<>/H<>#<23>[)<29><>E<EFBFBD><45>@N<>q<EFBFBD><71>툎<EFBFBD>r2<19>)D<><03>0<EFBFBD><30>j<EFBFBD>C<EFBFBD><1D><>L<07><>aC<61><43>&<26>4B<34>v]$E<><45><EFBFBD><1D>Iӑe<D391><65><EFBFBD><EFBFBD>P<EFBFBD>r<EFBFBD>I<EFBFBD>s<EFBFBD>e<EFBFBD>z<EFBFBD>˳~_
 | 
				
			||||||
 | 
					<EFBFBD><EFBFBD><EFBFBD>[y<03><><EFBFBD><EFBFBD>v<EFBFBD><76>W<EFBFBD><57>V=헛<>˘<EFBFBD>H	vZ~s<>@݉%<25><><EFBFBD><EFBFBD>?T<>ZH
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							@@ -1 +1 @@
 | 
				
			|||||||
2c54faec6c45d31c1abfaecdab471eac6633738a
 | 
					0cf15c3f66ec8384480ed9c3cf87c9e97fbb0ec3
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,7 +22,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	reservedWikiNames = []string{"_pages", "_new", "_edit"}
 | 
						reservedWikiNames = []string{"_pages", "_new", "_edit", "raw"}
 | 
				
			||||||
	wikiWorkingPool   = sync.NewExclusivePool()
 | 
						wikiWorkingPool   = sync.NewExclusivePool()
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,7 @@ func createContext(req *http.Request) (*macaron.Context, *httptest.ResponseRecor
 | 
				
			|||||||
	c := &macaron.Context{
 | 
						c := &macaron.Context{
 | 
				
			||||||
		Injector: inject.New(),
 | 
							Injector: inject.New(),
 | 
				
			||||||
		Req:      macaron.Request{Request: req},
 | 
							Req:      macaron.Request{Request: req},
 | 
				
			||||||
		Resp:     macaron.NewResponseWriter(resp),
 | 
							Resp:     macaron.NewResponseWriter(req.Method, resp),
 | 
				
			||||||
		Render:   &macaron.DummyRender{ResponseWriter: resp},
 | 
							Render:   &macaron.DummyRender{ResponseWriter: resp},
 | 
				
			||||||
		Data:     make(map[string]interface{}),
 | 
							Data:     make(map[string]interface{}),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -295,26 +295,41 @@ func WikiRaw(ctx *context.Context) {
 | 
				
			|||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	providedPath := ctx.Params("*")
 | 
						providedPath := ctx.Params("*")
 | 
				
			||||||
	if strings.HasSuffix(providedPath, ".md") {
 | 
					
 | 
				
			||||||
		providedPath = providedPath[:len(providedPath)-3]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	wikiPath := models.WikiNameToFilename(providedPath)
 | 
					 | 
				
			||||||
	var entry *git.TreeEntry
 | 
						var entry *git.TreeEntry
 | 
				
			||||||
	if commit != nil {
 | 
						if commit != nil {
 | 
				
			||||||
		entry, err = findEntryForFile(commit, wikiPath)
 | 
							// Try to find a file with that name
 | 
				
			||||||
 | 
							entry, err = findEntryForFile(commit, providedPath)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								ctx.ServerError("findFile", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if entry == nil {
 | 
				
			||||||
 | 
								// Try to find a wiki page with that name
 | 
				
			||||||
 | 
								if strings.HasSuffix(providedPath, ".md") {
 | 
				
			||||||
 | 
									providedPath = providedPath[:len(providedPath)-3]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								wikiPath := models.WikiNameToFilename(providedPath)
 | 
				
			||||||
 | 
								entry, err = findEntryForFile(commit, wikiPath)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									ctx.ServerError("findFile", err)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
					
 | 
				
			||||||
		ctx.ServerError("findFile", err)
 | 
						if entry != nil {
 | 
				
			||||||
		return
 | 
							if err = ServeBlob(ctx, entry.Blob()); err != nil {
 | 
				
			||||||
	} else if entry == nil {
 | 
								ctx.ServerError("ServeBlob", err)
 | 
				
			||||||
		ctx.NotFound("findEntryForFile", nil)
 | 
							}
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = ServeBlob(ctx, entry.Blob()); err != nil {
 | 
						ctx.NotFound("findEntryForFile", nil)
 | 
				
			||||||
		ctx.ServerError("ServeBlob", err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewWiki render wiki create page
 | 
					// NewWiki render wiki create page
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,7 +77,7 @@ func TestWiki(t *testing.T) {
 | 
				
			|||||||
	Wiki(ctx)
 | 
						Wiki(ctx)
 | 
				
			||||||
	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
 | 
						assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
 | 
				
			||||||
	assert.EqualValues(t, "Home", ctx.Data["Title"])
 | 
						assert.EqualValues(t, "Home", ctx.Data["Title"])
 | 
				
			||||||
	assertPagesMetas(t, []string{"Home"}, ctx.Data["Pages"])
 | 
						assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name"}, ctx.Data["Pages"])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestWikiPages(t *testing.T) {
 | 
					func TestWikiPages(t *testing.T) {
 | 
				
			||||||
@@ -87,7 +87,7 @@ func TestWikiPages(t *testing.T) {
 | 
				
			|||||||
	test.LoadRepo(t, ctx, 1)
 | 
						test.LoadRepo(t, ctx, 1)
 | 
				
			||||||
	WikiPages(ctx)
 | 
						WikiPages(ctx)
 | 
				
			||||||
	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
 | 
						assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
 | 
				
			||||||
	assertPagesMetas(t, []string{"Home"}, ctx.Data["Pages"])
 | 
						assertPagesMetas(t, []string{"Home", "Page With Image", "Page With Spaced Name"}, ctx.Data["Pages"])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNewWiki(t *testing.T) {
 | 
					func TestNewWiki(t *testing.T) {
 | 
				
			||||||
@@ -185,3 +185,23 @@ func TestDeleteWikiPagePost(t *testing.T) {
 | 
				
			|||||||
	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
 | 
						assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
 | 
				
			||||||
	assertWikiNotExists(t, ctx.Repo.Repository, "Home")
 | 
						assertWikiNotExists(t, ctx.Repo.Repository, "Home")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestWikiRaw(t *testing.T) {
 | 
				
			||||||
 | 
						for filepath, filetype := range map[string]string{
 | 
				
			||||||
 | 
							"jpeg.jpg":                 "image/jpeg",
 | 
				
			||||||
 | 
							"Page With Spaced Name":    "text/plain; charset=utf-8",
 | 
				
			||||||
 | 
							"Page-With-Spaced-Name":    "text/plain; charset=utf-8",
 | 
				
			||||||
 | 
							"Page With Spaced Name.md": "text/plain; charset=utf-8",
 | 
				
			||||||
 | 
							"Page-With-Spaced-Name.md": "text/plain; charset=utf-8",
 | 
				
			||||||
 | 
						} {
 | 
				
			||||||
 | 
							models.PrepareTestEnv(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ctx := test.MockContext(t, "user2/repo1/wiki/raw/"+filepath)
 | 
				
			||||||
 | 
							ctx.SetParams("*", filepath)
 | 
				
			||||||
 | 
							test.LoadUser(t, ctx, 2)
 | 
				
			||||||
 | 
							test.LoadRepo(t, ctx, 1)
 | 
				
			||||||
 | 
							WikiRaw(ctx)
 | 
				
			||||||
 | 
							assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
 | 
				
			||||||
 | 
							assert.EqualValues(t, filetype, ctx.Resp.Header().Get("Content-Type"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								vendor/gopkg.in/macaron.v1/context.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/gopkg.in/macaron.v1/context.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -262,7 +262,7 @@ func (ctx *Context) Params(name string) string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// SetParams sets value of param with given name.
 | 
					// SetParams sets value of param with given name.
 | 
				
			||||||
func (ctx *Context) SetParams(name, val string) {
 | 
					func (ctx *Context) SetParams(name, val string) {
 | 
				
			||||||
	if !strings.HasPrefix(name, ":") {
 | 
						if name != "*" && !strings.HasPrefix(name, ":") {
 | 
				
			||||||
		name = ":" + name
 | 
							name = ":" + name
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.params[name] = val
 | 
						ctx.params[name] = val
 | 
				
			||||||
@@ -270,7 +270,7 @@ func (ctx *Context) SetParams(name, val string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ReplaceAllParams replace all current params with given params
 | 
					// ReplaceAllParams replace all current params with given params
 | 
				
			||||||
func (ctx *Context) ReplaceAllParams(params Params) {
 | 
					func (ctx *Context) ReplaceAllParams(params Params) {
 | 
				
			||||||
	ctx.params = params;
 | 
						ctx.params = params
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ParamsEscape returns escapred params result.
 | 
					// ParamsEscape returns escapred params result.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								vendor/gopkg.in/macaron.v1/macaron.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/gopkg.in/macaron.v1/macaron.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -32,7 +32,7 @@ import (
 | 
				
			|||||||
	"github.com/go-macaron/inject"
 | 
						"github.com/go-macaron/inject"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const _VERSION = "1.2.4.1123"
 | 
					const _VERSION = "1.3.2.1216"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Version() string {
 | 
					func Version() string {
 | 
				
			||||||
	return _VERSION
 | 
						return _VERSION
 | 
				
			||||||
@@ -194,7 +194,7 @@ func (m *Macaron) createContext(rw http.ResponseWriter, req *http.Request) *Cont
 | 
				
			|||||||
		index:    0,
 | 
							index:    0,
 | 
				
			||||||
		Router:   m.Router,
 | 
							Router:   m.Router,
 | 
				
			||||||
		Req:      Request{req},
 | 
							Req:      Request{req},
 | 
				
			||||||
		Resp:     NewResponseWriter(rw),
 | 
							Resp:     NewResponseWriter(req.Method, rw),
 | 
				
			||||||
		Render:   &DummyRender{rw},
 | 
							Render:   &DummyRender{rw},
 | 
				
			||||||
		Data:     make(map[string]interface{}),
 | 
							Data:     make(map[string]interface{}),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								vendor/gopkg.in/macaron.v1/response_writer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								vendor/gopkg.in/macaron.v1/response_writer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -42,11 +42,12 @@ type ResponseWriter interface {
 | 
				
			|||||||
type BeforeFunc func(ResponseWriter)
 | 
					type BeforeFunc func(ResponseWriter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
 | 
					// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
 | 
				
			||||||
func NewResponseWriter(rw http.ResponseWriter) ResponseWriter {
 | 
					func NewResponseWriter(method string, rw http.ResponseWriter) ResponseWriter {
 | 
				
			||||||
	return &responseWriter{rw, 0, 0, nil}
 | 
						return &responseWriter{method, rw, 0, 0, nil}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type responseWriter struct {
 | 
					type responseWriter struct {
 | 
				
			||||||
 | 
						method string
 | 
				
			||||||
	http.ResponseWriter
 | 
						http.ResponseWriter
 | 
				
			||||||
	status      int
 | 
						status      int
 | 
				
			||||||
	size        int
 | 
						size        int
 | 
				
			||||||
@@ -59,13 +60,15 @@ func (rw *responseWriter) WriteHeader(s int) {
 | 
				
			|||||||
	rw.status = s
 | 
						rw.status = s
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (rw *responseWriter) Write(b []byte) (int, error) {
 | 
					func (rw *responseWriter) Write(b []byte) (size int, err error) {
 | 
				
			||||||
	if !rw.Written() {
 | 
						if !rw.Written() {
 | 
				
			||||||
		// The status will be StatusOK if WriteHeader has not been called yet
 | 
							// The status will be StatusOK if WriteHeader has not been called yet
 | 
				
			||||||
		rw.WriteHeader(http.StatusOK)
 | 
							rw.WriteHeader(http.StatusOK)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	size, err := rw.ResponseWriter.Write(b)
 | 
						if rw.method != "HEAD" {
 | 
				
			||||||
	rw.size += size
 | 
							size, err = rw.ResponseWriter.Write(b)
 | 
				
			||||||
 | 
							rw.size += size
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return size, err
 | 
						return size, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								vendor/gopkg.in/macaron.v1/router.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/gopkg.in/macaron.v1/router.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -96,7 +96,7 @@ func NewRouter() *Router {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SetAutoHead sets the value who determines whether add HEAD method automatically
 | 
					// SetAutoHead sets the value who determines whether add HEAD method automatically
 | 
				
			||||||
// when GET method is added. Combo router will not be affected by this value.
 | 
					// when GET method is added.
 | 
				
			||||||
func (r *Router) SetAutoHead(v bool) {
 | 
					func (r *Router) SetAutoHead(v bool) {
 | 
				
			||||||
	r.autoHead = v
 | 
						r.autoHead = v
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -341,6 +341,9 @@ func (cr *ComboRouter) route(fn func(string, ...Handler) *Route, method string,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (cr *ComboRouter) Get(h ...Handler) *ComboRouter {
 | 
					func (cr *ComboRouter) Get(h ...Handler) *ComboRouter {
 | 
				
			||||||
 | 
						if cr.router.autoHead {
 | 
				
			||||||
 | 
							cr.Head(h...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return cr.route(cr.router.Get, "GET", h...)
 | 
						return cr.route(cr.router.Get, "GET", h...)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user