@@ -20,6 +20,8 @@ import (
2020	unit_model "code.gitea.io/gitea/models/unit" 
2121	user_model "code.gitea.io/gitea/models/user" 
2222	"code.gitea.io/gitea/modules/git" 
23+ 	giturl "code.gitea.io/gitea/modules/git/url" 
24+ 	"code.gitea.io/gitea/modules/httplib" 
2325	"code.gitea.io/gitea/modules/log" 
2426	repo_module "code.gitea.io/gitea/modules/repository" 
2527	"code.gitea.io/gitea/modules/setting" 
@@ -302,8 +304,33 @@ func handleRepoEmptyOrBroken(ctx *context.Context) {
302304	ctx .Redirect (link )
303305}
304306
307+ func  handleRepoViewSubmodule (ctx  * context.Context , submodule  * git.SubModule ) {
308+ 	submoduleRepoURL , err  :=  giturl .ParseRepositoryURL (ctx , submodule .URL )
309+ 	if  err  !=  nil  {
310+ 		HandleGitError (ctx , "prepareToRenderDirOrFile: ParseRepositoryURL" , err )
311+ 		return 
312+ 	}
313+ 	submoduleURL  :=  giturl .MakeRepositoryWebLink (submoduleRepoURL )
314+ 	if  httplib .IsCurrentGiteaSiteURL (ctx , submoduleURL ) {
315+ 		ctx .RedirectToCurrentSite (submoduleURL )
316+ 	} else  {
317+ 		// don't auto-redirect to external URL, to avoid open redirect or phishing 
318+ 		ctx .Data ["NotFoundPrompt" ] =  submoduleURL 
319+ 		ctx .NotFound (nil )
320+ 	}
321+ }
322+ 
305323func  prepareToRenderDirOrFile (entry  * git.TreeEntry ) func (ctx  * context.Context ) {
306324	return  func (ctx  * context.Context ) {
325+ 		if  entry .IsSubModule () {
326+ 			submodule , err  :=  ctx .Repo .Commit .GetSubModule (entry .Name ())
327+ 			if  err  !=  nil  {
328+ 				HandleGitError (ctx , "prepareToRenderDirOrFile: GetSubModule" , err )
329+ 				return 
330+ 			}
331+ 			handleRepoViewSubmodule (ctx , submodule )
332+ 			return 
333+ 		}
307334		if  entry .IsDir () {
308335			prepareToRenderDirectory (ctx )
309336		} else  {
0 commit comments