diff --git a/services/updateserver/joomla.go b/services/updateserver/joomla.go index 1c6cdb41a6..f56758c973 100644 --- a/services/updateserver/joomla.go +++ b/services/updateserver/joomla.go @@ -7,12 +7,14 @@ import ( "context" "encoding/xml" "fmt" + "io" "strings" "time" "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/db" "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/licenses" repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo" + "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/storage" "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/setting" ) @@ -246,14 +248,25 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require continue } - // Find the first .zip attachment as the download URL. - var downloadURL string + // Find the first .zip attachment as the download URL, and its SHA256 sidecar. + var downloadURL, sha256Hash string + var zipName string for _, att := range rel.Attachments { - if strings.HasSuffix(strings.ToLower(att.Name), ".zip") { + if strings.HasSuffix(strings.ToLower(att.Name), ".zip") && !strings.HasSuffix(att.Name, ".sha256") { downloadURL = fmt.Sprintf("%s/releases/download/%s/%s", repoLink, rel.TagName, att.Name) + zipName = att.Name break } } + // Look for the SHA256 sidecar file. + if zipName != "" { + for _, att := range rel.Attachments { + if att.Name == zipName+".sha256" { + sha256Hash = readSHA256FromSidecar(ctx, att) + break + } + } + } // Fall back to the release tag archive if no zip attachment. if downloadURL == "" { downloadURL = fmt.Sprintf("%s/archive/%s.zip", repoLink, rel.TagName) @@ -302,6 +315,7 @@ func GenerateJoomlaXML(ctx context.Context, repo *repo_model.Repository, require Maintainer: maintainer, MaintainerURL: maintainerURL, PHPMinimum: phpMinimum, + SHA256: sha256Hash, TargetPlatform: xmlTargetPlat{ Name: "joomla", Version: targetVersion, @@ -354,3 +368,25 @@ func channelSuffix(channel string) string { return "" } } + +// readSHA256FromSidecar reads the SHA256 hash from a .sha256 sidecar attachment. +// The sidecar format is: " \n" +func readSHA256FromSidecar(_ context.Context, att *repo_model.Attachment) string { + fr, err := storage.Attachments.Open(att.RelativePath()) + if err != nil { + return "" + } + defer fr.Close() + + data, err := io.ReadAll(io.LimitReader(fr, 256)) + if err != nil { + return "" + } + + content := strings.TrimSpace(string(data)) + // Format: "hexhash filename" + if idx := strings.Index(content, " "); idx > 0 { + return content[:idx] + } + return content +}