@@ -20,6 +20,8 @@ import (
20
20
unit_model "code.gitea.io/gitea/models/unit"
21
21
user_model "code.gitea.io/gitea/models/user"
22
22
"code.gitea.io/gitea/modules/git"
23
+ giturl "code.gitea.io/gitea/modules/git/url"
24
+ "code.gitea.io/gitea/modules/httplib"
23
25
"code.gitea.io/gitea/modules/log"
24
26
repo_module "code.gitea.io/gitea/modules/repository"
25
27
"code.gitea.io/gitea/modules/setting"
@@ -302,8 +304,33 @@ func handleRepoEmptyOrBroken(ctx *context.Context) {
302
304
ctx .Redirect (link )
303
305
}
304
306
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
+
305
323
func prepareToRenderDirOrFile (entry * git.TreeEntry ) func (ctx * context.Context ) {
306
324
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
+ }
307
334
if entry .IsDir () {
308
335
prepareToRenderDirectory (ctx )
309
336
} else {
0 commit comments