gitea源码

artifacts_utils.go 3.2KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright 2023 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package actions
  4. import (
  5. "crypto/md5"
  6. "fmt"
  7. "net/http"
  8. "strconv"
  9. "strings"
  10. "code.gitea.io/gitea/models/actions"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/util"
  13. )
  14. const (
  15. artifactXTfsFileLengthHeader = "x-tfs-filelength"
  16. artifactXActionsResultsMD5Header = "x-actions-results-md5"
  17. )
  18. // The rules are from https://github.com/actions/toolkit/blob/main/packages/artifact/src/internal/path-and-artifact-name-validation.ts#L32
  19. var invalidArtifactNameChars = strings.Join([]string{"\\", "/", "\"", ":", "<", ">", "|", "*", "?", "\r", "\n"}, "")
  20. func validateArtifactName(ctx *ArtifactContext, artifactName string) bool {
  21. if strings.ContainsAny(artifactName, invalidArtifactNameChars) {
  22. log.Error("Error checking artifact name contains invalid character")
  23. ctx.HTTPError(http.StatusBadRequest, "Error checking artifact name contains invalid character")
  24. return false
  25. }
  26. return true
  27. }
  28. func validateRunID(ctx *ArtifactContext) (*actions.ActionTask, int64, bool) {
  29. task := ctx.ActionTask
  30. runID := ctx.PathParamInt64("run_id")
  31. if task.Job.RunID != runID {
  32. log.Error("Error runID not match")
  33. ctx.HTTPError(http.StatusBadRequest, "run-id does not match")
  34. return nil, 0, false
  35. }
  36. return task, runID, true
  37. }
  38. func validateRunIDV4(ctx *ArtifactContext, rawRunID string) (*actions.ActionTask, int64, bool) { //nolint:unparam // ActionTask is never used
  39. task := ctx.ActionTask
  40. runID, err := strconv.ParseInt(rawRunID, 10, 64)
  41. if err != nil || task.Job.RunID != runID {
  42. log.Error("Error runID not match")
  43. ctx.HTTPError(http.StatusBadRequest, "run-id does not match")
  44. return nil, 0, false
  45. }
  46. return task, runID, true
  47. }
  48. func validateArtifactHash(ctx *ArtifactContext, artifactName string) bool {
  49. paramHash := ctx.PathParam("artifact_hash")
  50. // use artifact name to create upload url
  51. artifactHash := fmt.Sprintf("%x", md5.Sum([]byte(artifactName)))
  52. if paramHash == artifactHash {
  53. return true
  54. }
  55. log.Error("Invalid artifact hash: %s", paramHash)
  56. ctx.HTTPError(http.StatusBadRequest, "Invalid artifact hash")
  57. return false
  58. }
  59. func parseArtifactItemPath(ctx *ArtifactContext) (string, string, bool) {
  60. // itemPath is generated from upload-artifact action
  61. // it's formatted as {artifact_name}/{artfict_path_in_runner}
  62. // act_runner in host mode on Windows, itemPath is joined by Windows slash '\'
  63. itemPath := util.PathJoinRelX(ctx.Req.URL.Query().Get("itemPath"))
  64. artifactName := strings.Split(itemPath, "/")[0]
  65. artifactPath := strings.TrimPrefix(itemPath, artifactName+"/")
  66. if !validateArtifactHash(ctx, artifactName) {
  67. return "", "", false
  68. }
  69. if !validateArtifactName(ctx, artifactName) {
  70. return "", "", false
  71. }
  72. return artifactName, artifactPath, true
  73. }
  74. // getUploadFileSize returns the size of the file to be uploaded.
  75. // The raw size is the size of the file as reported by the header X-TFS-FileLength.
  76. func getUploadFileSize(ctx *ArtifactContext) (int64, int64) {
  77. contentLength := ctx.Req.ContentLength
  78. xTfsLength, _ := strconv.ParseInt(ctx.Req.Header.Get(artifactXTfsFileLengthHeader), 10, 64)
  79. if xTfsLength > 0 {
  80. return xTfsLength, contentLength
  81. }
  82. return contentLength, contentLength
  83. }