You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

external.go 2.2 kB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package external
  5. import (
  6. "bytes"
  7. "io"
  8. "io/ioutil"
  9. "os"
  10. "os/exec"
  11. "strings"
  12. "code.gitea.io/gitea/modules/log"
  13. "code.gitea.io/gitea/modules/markup"
  14. "code.gitea.io/gitea/modules/setting"
  15. )
  16. // RegisterParsers registers all supported third part parsers according settings
  17. func RegisterParsers() {
  18. for _, parser := range setting.ExternalMarkupParsers {
  19. if parser.Enabled && parser.Command != "" && len(parser.FileExtensions) > 0 {
  20. markup.RegisterParser(&Parser{parser})
  21. }
  22. }
  23. }
  24. // Parser implements markup.Parser for external tools
  25. type Parser struct {
  26. setting.MarkupParser
  27. }
  28. // Name returns the external tool name
  29. func (p *Parser) Name() string {
  30. return p.MarkupName
  31. }
  32. // Extensions returns the supported extensions of the tool
  33. func (p *Parser) Extensions() []string {
  34. return p.FileExtensions
  35. }
  36. // Render renders the data of the document to HTML via the external tool.
  37. func (p *Parser) Render(rawBytes []byte, urlPrefix string, metas map[string]string, isWiki bool) []byte {
  38. var (
  39. bs []byte
  40. buf = bytes.NewBuffer(bs)
  41. rd = bytes.NewReader(rawBytes)
  42. commands = strings.Fields(p.Command)
  43. args = commands[1:]
  44. )
  45. if p.IsInputFile {
  46. // write to temp file
  47. f, err := ioutil.TempFile("", "gitea_input")
  48. if err != nil {
  49. log.Error(4, "%s create temp file when rendering %s failed: %v", p.Name(), p.Command, err)
  50. return []byte("")
  51. }
  52. defer os.Remove(f.Name())
  53. _, err = io.Copy(f, rd)
  54. if err != nil {
  55. f.Close()
  56. log.Error(4, "%s write data to temp file when rendering %s failed: %v", p.Name(), p.Command, err)
  57. return []byte("")
  58. }
  59. err = f.Close()
  60. if err != nil {
  61. log.Error(4, "%s close temp file when rendering %s failed: %v", p.Name(), p.Command, err)
  62. return []byte("")
  63. }
  64. args = append(args, f.Name())
  65. }
  66. cmd := exec.Command(commands[0], args...)
  67. if !p.IsInputFile {
  68. cmd.Stdin = rd
  69. }
  70. cmd.Stdout = buf
  71. if err := cmd.Run(); err != nil {
  72. log.Error(4, "%s render run command %s %v failed: %v", p.Name(), commands[0], args, err)
  73. return []byte("")
  74. }
  75. return buf.Bytes()
  76. }