parse.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package repository
  2. import (
  3. "errors"
  4. "path/filepath"
  5. "runtime"
  6. "strings"
  7. uriParser "github.com/fredbi/uri"
  8. "fyne.io/fyne/v2"
  9. )
  10. // NewFileURI implements the back-end logic to storage.NewFileURI, which you
  11. // should use instead. This is only here because other functions in repository
  12. // need to call it, and it prevents a circular import.
  13. //
  14. // Since: 2.0
  15. func NewFileURI(path string) fyne.URI {
  16. // URIs are supposed to use forward slashes. On Windows, it
  17. // should be OK to use the platform native filepath with UNIX
  18. // or NT style paths, with / or \, but when we reconstruct
  19. // the URI, we want to have / only.
  20. if runtime.GOOS == "windows" {
  21. // seems that sometimes we end up with
  22. // double-backslashes
  23. path = filepath.ToSlash(path)
  24. }
  25. return &uri{
  26. scheme: "file",
  27. path: path,
  28. }
  29. }
  30. // ParseURI implements the back-end logic for storage.ParseURI, which you
  31. // should use instead. This is only here because other functions in repository
  32. // need to call it, and it prevents a circular import.
  33. //
  34. // Since: 2.0
  35. func ParseURI(s string) (fyne.URI, error) {
  36. // Extract the scheme.
  37. colonIndex := strings.IndexByte(s, ':')
  38. if colonIndex <= 0 {
  39. return nil, errors.New("invalid URI, scheme must be present")
  40. }
  41. scheme := strings.ToLower(s[:colonIndex])
  42. if scheme == "file" {
  43. // Does this really deserve to be special? In principle, the
  44. // purpose of this check is to pass it to NewFileURI, which
  45. // allows platform path seps in the URI (against the RFC, but
  46. // easier for people building URIs naively on Windows). Maybe
  47. // we should punt this to whoever generated the URI in the
  48. // first place?
  49. if len(s) <= 7 {
  50. return nil, errors.New("not a valid URI")
  51. }
  52. path := s[5:] // everything after file:
  53. if len(path) > 2 && path[:2] == "//" {
  54. path = path[2:]
  55. }
  56. // Windows files can break authority checks, so just return the parsed file URI
  57. return NewFileURI(path), nil
  58. }
  59. repo, err := ForScheme(scheme)
  60. if err == nil {
  61. // If the repository registered for this scheme implements a parser
  62. if c, ok := repo.(CustomURIRepository); ok {
  63. return c.ParseURI(s)
  64. }
  65. }
  66. // There was no repository registered, or it did not provide a parser
  67. l, err := uriParser.Parse(s)
  68. if err != nil {
  69. return nil, err
  70. }
  71. authority := ""
  72. if userInfo := l.Authority().UserInfo(); len(userInfo) > 0 {
  73. authority += userInfo + "@"
  74. }
  75. authority += l.Authority().Host()
  76. if port := l.Authority().Port(); len(port) > 0 {
  77. authority += ":" + port
  78. }
  79. return &uri{
  80. scheme: scheme,
  81. authority: authority,
  82. path: l.Authority().Path(),
  83. query: l.Query().Encode(),
  84. fragment: l.Fragment(),
  85. }, nil
  86. }