atom_03.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package atom // import "miniflux.app/v2/internal/reader/atom"
  4. import (
  5. "encoding/base64"
  6. "html"
  7. "strings"
  8. )
  9. // Specs: http://web.archive.org/web/20060811235523/http://www.mnot.net/drafts/draft-nottingham-atom-format-02.html
  10. type atom03Feed struct {
  11. Version string `xml:"version,attr"`
  12. // Language is the natural language of the feed, declared by an
  13. // xml:lang attribute on the atom:feed element. The tag is
  14. // namespace-qualified so that lang attributes from other namespaces
  15. // cannot override the real xml:lang value.
  16. Language string `xml:"http://www.w3.org/XML/1998/namespace lang,attr"`
  17. // The "atom:id" element's content conveys a permanent, globally unique identifier for the feed.
  18. // It MUST NOT change over time, even if the feed is relocated. atom:feed elements MAY contain an atom:id element,
  19. // but MUST NOT contain more than one. The content of this element, when present, MUST be a URI.
  20. ID string `xml:"http://purl.org/atom/ns# id"`
  21. // The "atom:title" element is a Content construct that conveys a human-readable title for the feed.
  22. // atom:feed elements MUST contain exactly one atom:title element.
  23. // If the feed describes a Web resource, its content SHOULD be the same as that resource's title.
  24. Title atom03Content `xml:"http://purl.org/atom/ns# title"`
  25. // The "atom:link" element is a Link construct that conveys a URI associated with the feed.
  26. // The nature of the relationship as well as the link itself is determined by the element's content.
  27. // atom:feed elements MUST contain at least one atom:link element with a rel attribute value of "alternate".
  28. // atom:feed elements MUST NOT contain more than one atom:link element with a rel attribute value of "alternate" that has the same type attribute value.
  29. // atom:feed elements MAY contain additional atom:link elements beyond those described above.
  30. Links atomLinks `xml:"http://purl.org/atom/ns# link"`
  31. // The "atom:author" element is a Person construct that indicates the default author of the feed.
  32. // atom:feed elements MUST contain exactly one atom:author element,
  33. // UNLESS all of the atom:feed element's child atom:entry elements contain an atom:author element.
  34. // atom:feed elements MUST NOT contain more than one atom:author element.
  35. Author AtomPerson `xml:"http://purl.org/atom/ns# author"`
  36. // The "atom:entry" element's represents an individual entry that is contained by the feed.
  37. // atom:feed elements MAY contain one or more atom:entry elements.
  38. Entries []atom03Entry `xml:"http://purl.org/atom/ns# entry"`
  39. }
  40. type atom03Entry struct {
  41. // The "atom:id" element's content conveys a permanent, globally unique identifier for the entry.
  42. // It MUST NOT change over time, even if other representations of the entry (such as a web representation pointed to by the entry's atom:link element) are relocated.
  43. // If the same entry is syndicated in two atom:feeds published by the same entity, the entry's atom:id MUST be the same in both feeds.
  44. ID string `xml:"id"`
  45. // Language is the natural language of the entry, declared by an
  46. // xml:lang attribute on the atom:entry element. The tag is
  47. // namespace-qualified so that lang attributes from other namespaces
  48. // cannot override the real xml:lang value.
  49. Language string `xml:"http://www.w3.org/XML/1998/namespace lang,attr"`
  50. // The "atom:title" element is a Content construct that conveys a human-readable title for the entry.
  51. // atom:entry elements MUST have exactly one "atom:title" element.
  52. // If an entry describes a Web resource, its content SHOULD be the same as that resource's title.
  53. Title atom03Content `xml:"title"`
  54. // The "atom:modified" element is a Date construct that indicates the time that the entry was last modified.
  55. // atom:entry elements MUST contain an atom:modified element, but MUST NOT contain more than one.
  56. // The content of an atom:modified element MUST have a time zone whose value SHOULD be "UTC".
  57. Modified string `xml:"modified"`
  58. // The "atom:issued" element is a Date construct that indicates the time that the entry was issued.
  59. // atom:entry elements MUST contain an atom:issued element, but MUST NOT contain more than one.
  60. // The content of an atom:issued element MAY omit a time zone.
  61. Issued string `xml:"issued"`
  62. // The "atom:created" element is a Date construct that indicates the time that the entry was created.
  63. // atom:entry elements MAY contain an atom:created element, but MUST NOT contain more than one.
  64. // The content of an atom:created element MUST have a time zone whose value SHOULD be "UTC".
  65. // If atom:created is not present, its content MUST considered to be the same as that of atom:modified.
  66. Created string `xml:"created"`
  67. // The "atom:link" element is a Link construct that conveys a URI associated with the entry.
  68. // The nature of the relationship as well as the link itself is determined by the element's content.
  69. // atom:entry elements MUST contain at least one atom:link element with a rel attribute value of "alternate".
  70. // atom:entry elements MUST NOT contain more than one atom:link element with a rel attribute value of "alternate" that has the same type attribute value.
  71. // atom:entry elements MAY contain additional atom:link elements beyond those described above.
  72. Links atomLinks `xml:"link"`
  73. // The "atom:summary" element is a Content construct that conveys a short summary, abstract or excerpt of the entry.
  74. // atom:entry elements MAY contain an atom:created element, but MUST NOT contain more than one.
  75. Summary atom03Content `xml:"summary"`
  76. // The "atom:content" element is a Content construct that conveys the content of the entry.
  77. // atom:entry elements MAY contain one or more atom:content elements.
  78. Content atom03Content `xml:"content"`
  79. // The "atom:author" element is a Person construct that indicates the default author of the entry.
  80. // atom:entry elements MUST contain exactly one atom:author element,
  81. // UNLESS the atom:feed element containing them contains an atom:author element itself.
  82. // atom:entry elements MUST NOT contain more than one atom:author element.
  83. Author AtomPerson `xml:"author"`
  84. }
  85. type atom03Content struct {
  86. // Content constructs MAY have a "type" attribute, whose value indicates the media type of the content.
  87. // When present, this attribute's value MUST be a registered media type [RFC2045].
  88. // If not present, its value MUST be considered to be "text/plain".
  89. Type string `xml:"type,attr"`
  90. // Content constructs MAY have a "mode" attribute, whose value indicates the method used to encode the content.
  91. // When present, this attribute's value MUST be listed below.
  92. // If not present, its value MUST be considered to be "xml".
  93. //
  94. // "xml": A mode attribute with the value "xml" indicates that the element's content is inline xml (for example, namespace-qualified XHTML).
  95. //
  96. // "escaped": A mode attribute with the value "escaped" indicates that the element's content is an escaped string.
  97. // Processors MUST unescape the element's content before considering it as content of the indicated media type.
  98. //
  99. // "base64": A mode attribute with the value "base64" indicates that the element's content is base64-encoded [RFC2045].
  100. // Processors MUST decode the element's content before considering it as content of the the indicated media type.
  101. Mode string `xml:"mode,attr"`
  102. CharData string `xml:",chardata"`
  103. InnerXML string `xml:",innerxml"`
  104. }
  105. func (a *atom03Content) content() string {
  106. content := ""
  107. switch a.Mode {
  108. case "xml":
  109. content = a.InnerXML
  110. case "escaped":
  111. content = a.CharData
  112. case "base64":
  113. b, err := base64.StdEncoding.DecodeString(a.CharData)
  114. if err == nil {
  115. content = string(b)
  116. }
  117. default:
  118. content = a.CharData
  119. }
  120. if a.Type != "text/html" {
  121. content = html.EscapeString(content)
  122. }
  123. return strings.TrimSpace(content)
  124. }