feedtools 0.2.26 → 0.2.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. data/CHANGELOG +232 -216
  2. data/db/migration.rb +2 -0
  3. data/db/schema.mysql.sql +2 -0
  4. data/db/schema.postgresql.sql +3 -1
  5. data/db/schema.sqlite.sql +3 -1
  6. data/lib/feed_tools.rb +37 -14
  7. data/lib/feed_tools/database_feed_cache.rb +13 -2
  8. data/lib/feed_tools/feed.rb +430 -104
  9. data/lib/feed_tools/feed_item.rb +533 -268
  10. data/lib/feed_tools/helpers/generic_helper.rb +1 -1
  11. data/lib/feed_tools/helpers/html_helper.rb +78 -116
  12. data/lib/feed_tools/helpers/retrieval_helper.rb +33 -3
  13. data/lib/feed_tools/helpers/uri_helper.rb +46 -54
  14. data/lib/feed_tools/monkey_patch.rb +27 -1
  15. data/lib/feed_tools/vendor/html5/History.txt +10 -0
  16. data/lib/feed_tools/vendor/html5/Manifest.txt +117 -0
  17. data/lib/feed_tools/vendor/html5/README +45 -0
  18. data/lib/feed_tools/vendor/html5/Rakefile.rb +33 -0
  19. data/lib/feed_tools/vendor/html5/bin/html5 +217 -0
  20. data/lib/feed_tools/vendor/html5/lib/core_ext/string.rb +17 -0
  21. data/lib/feed_tools/vendor/html5/lib/html5.rb +13 -0
  22. data/lib/feed_tools/vendor/html5/lib/html5/constants.rb +1046 -0
  23. data/lib/feed_tools/vendor/html5/lib/html5/filters/base.rb +10 -0
  24. data/lib/feed_tools/vendor/html5/lib/html5/filters/inject_meta_charset.rb +82 -0
  25. data/lib/feed_tools/vendor/html5/lib/html5/filters/iso639codes.rb +752 -0
  26. data/lib/feed_tools/vendor/html5/lib/html5/filters/optionaltags.rb +198 -0
  27. data/lib/feed_tools/vendor/html5/lib/html5/filters/rfc2046.rb +30 -0
  28. data/lib/feed_tools/vendor/html5/lib/html5/filters/rfc3987.rb +89 -0
  29. data/lib/feed_tools/vendor/html5/lib/html5/filters/sanitizer.rb +15 -0
  30. data/lib/feed_tools/vendor/html5/lib/html5/filters/validator.rb +830 -0
  31. data/lib/feed_tools/vendor/html5/lib/html5/filters/whitespace.rb +36 -0
  32. data/lib/feed_tools/vendor/html5/lib/html5/html5parser.rb +248 -0
  33. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/after_body_phase.rb +46 -0
  34. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/after_frameset_phase.rb +33 -0
  35. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/after_head_phase.rb +50 -0
  36. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/before_head_phase.rb +41 -0
  37. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/in_body_phase.rb +613 -0
  38. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/in_caption_phase.rb +69 -0
  39. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/in_cell_phase.rb +78 -0
  40. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/in_column_group_phase.rb +55 -0
  41. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/in_frameset_phase.rb +57 -0
  42. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/in_head_phase.rb +138 -0
  43. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/in_row_phase.rb +89 -0
  44. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/in_select_phase.rb +85 -0
  45. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/in_table_body_phase.rb +86 -0
  46. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/in_table_phase.rb +115 -0
  47. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/initial_phase.rb +133 -0
  48. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/phase.rb +154 -0
  49. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/root_element_phase.rb +41 -0
  50. data/lib/feed_tools/vendor/html5/lib/html5/html5parser/trailing_end_phase.rb +35 -0
  51. data/lib/feed_tools/vendor/html5/lib/html5/inputstream.rb +648 -0
  52. data/lib/feed_tools/vendor/html5/lib/html5/liberalxmlparser.rb +158 -0
  53. data/lib/feed_tools/vendor/html5/lib/html5/sanitizer.rb +188 -0
  54. data/lib/feed_tools/vendor/html5/lib/html5/serializer.rb +2 -0
  55. data/lib/feed_tools/vendor/html5/lib/html5/serializer/htmlserializer.rb +179 -0
  56. data/lib/feed_tools/vendor/html5/lib/html5/serializer/xhtmlserializer.rb +20 -0
  57. data/lib/feed_tools/vendor/html5/lib/html5/sniffer.rb +45 -0
  58. data/lib/feed_tools/vendor/html5/lib/html5/tokenizer.rb +966 -0
  59. data/lib/feed_tools/vendor/html5/lib/html5/treebuilders.rb +24 -0
  60. data/lib/feed_tools/vendor/html5/lib/html5/treebuilders/base.rb +334 -0
  61. data/lib/feed_tools/vendor/html5/lib/html5/treebuilders/hpricot.rb +231 -0
  62. data/lib/feed_tools/vendor/html5/lib/html5/treebuilders/rexml.rb +209 -0
  63. data/lib/feed_tools/vendor/html5/lib/html5/treebuilders/simpletree.rb +185 -0
  64. data/lib/feed_tools/vendor/html5/lib/html5/treewalkers.rb +26 -0
  65. data/lib/feed_tools/vendor/html5/lib/html5/treewalkers/base.rb +162 -0
  66. data/lib/feed_tools/vendor/html5/lib/html5/treewalkers/hpricot.rb +48 -0
  67. data/lib/feed_tools/vendor/html5/lib/html5/treewalkers/rexml.rb +48 -0
  68. data/lib/feed_tools/vendor/html5/lib/html5/treewalkers/simpletree.rb +48 -0
  69. data/lib/feed_tools/vendor/html5/lib/html5/version.rb +3 -0
  70. data/lib/feed_tools/vendor/html5/testdata/encoding/chardet/test_big5.txt +51 -0
  71. data/lib/feed_tools/vendor/html5/testdata/encoding/test-yahoo-jp.dat +10 -0
  72. data/lib/feed_tools/vendor/html5/testdata/encoding/tests1.dat +394 -0
  73. data/lib/feed_tools/vendor/html5/testdata/encoding/tests2.dat +81 -0
  74. data/lib/feed_tools/vendor/html5/testdata/sanitizer/tests1.dat +416 -0
  75. data/lib/feed_tools/vendor/html5/testdata/serializer/core.test +104 -0
  76. data/lib/feed_tools/vendor/html5/testdata/serializer/injectmeta.test +65 -0
  77. data/lib/feed_tools/vendor/html5/testdata/serializer/optionaltags.test +900 -0
  78. data/lib/feed_tools/vendor/html5/testdata/serializer/options.test +60 -0
  79. data/lib/feed_tools/vendor/html5/testdata/serializer/whitespace.test +51 -0
  80. data/lib/feed_tools/vendor/html5/testdata/sites/google-results.htm +1 -0
  81. data/lib/feed_tools/vendor/html5/testdata/sites/python-ref-import.htm +1 -0
  82. data/lib/feed_tools/vendor/html5/testdata/sites/web-apps-old.htm +1 -0
  83. data/lib/feed_tools/vendor/html5/testdata/sites/web-apps.htm +34275 -0
  84. data/lib/feed_tools/vendor/html5/testdata/sniffer/htmlOrFeed.json +43 -0
  85. data/lib/feed_tools/vendor/html5/testdata/tokenizer/contentModelFlags.test +48 -0
  86. data/lib/feed_tools/vendor/html5/testdata/tokenizer/entities.test +2339 -0
  87. data/lib/feed_tools/vendor/html5/testdata/tokenizer/escapeFlag.test +21 -0
  88. data/lib/feed_tools/vendor/html5/testdata/tokenizer/test1.test +172 -0
  89. data/lib/feed_tools/vendor/html5/testdata/tokenizer/test2.test +129 -0
  90. data/lib/feed_tools/vendor/html5/testdata/tokenizer/test3.test +367 -0
  91. data/lib/feed_tools/vendor/html5/testdata/tokenizer/test4.test +198 -0
  92. data/lib/feed_tools/vendor/html5/testdata/tree-construction/tests1.dat +1950 -0
  93. data/lib/feed_tools/vendor/html5/testdata/tree-construction/tests2.dat +773 -0
  94. data/lib/feed_tools/vendor/html5/testdata/tree-construction/tests3.dat +270 -0
  95. data/lib/feed_tools/vendor/html5/testdata/tree-construction/tests4.dat +60 -0
  96. data/lib/feed_tools/vendor/html5/testdata/tree-construction/tests5.dat +175 -0
  97. data/lib/feed_tools/vendor/html5/testdata/tree-construction/tests6.dat +196 -0
  98. data/lib/feed_tools/vendor/html5/testdata/validator/attributes.test +1035 -0
  99. data/lib/feed_tools/vendor/html5/testdata/validator/base-href-attribute.test +787 -0
  100. data/lib/feed_tools/vendor/html5/testdata/validator/base-target-attribute.test +35 -0
  101. data/lib/feed_tools/vendor/html5/testdata/validator/blockquote-cite-attribute.test +7 -0
  102. data/lib/feed_tools/vendor/html5/testdata/validator/classattribute.test +152 -0
  103. data/lib/feed_tools/vendor/html5/testdata/validator/contenteditableattribute.test +59 -0
  104. data/lib/feed_tools/vendor/html5/testdata/validator/contextmenuattribute.test +115 -0
  105. data/lib/feed_tools/vendor/html5/testdata/validator/dirattribute.test +59 -0
  106. data/lib/feed_tools/vendor/html5/testdata/validator/draggableattribute.test +63 -0
  107. data/lib/feed_tools/vendor/html5/testdata/validator/html-xmlns-attribute.test +23 -0
  108. data/lib/feed_tools/vendor/html5/testdata/validator/idattribute.test +115 -0
  109. data/lib/feed_tools/vendor/html5/testdata/validator/inputattributes.test +2795 -0
  110. data/lib/feed_tools/vendor/html5/testdata/validator/irrelevantattribute.test +63 -0
  111. data/lib/feed_tools/vendor/html5/testdata/validator/langattribute.test +5579 -0
  112. data/lib/feed_tools/vendor/html5/testdata/validator/li-value-attribute.test +7 -0
  113. data/lib/feed_tools/vendor/html5/testdata/validator/link-href-attribute.test +7 -0
  114. data/lib/feed_tools/vendor/html5/testdata/validator/link-hreflang-attribute.test +7 -0
  115. data/lib/feed_tools/vendor/html5/testdata/validator/link-rel-attribute.test +271 -0
  116. data/lib/feed_tools/vendor/html5/testdata/validator/ol-start-attribute.test +7 -0
  117. data/lib/feed_tools/vendor/html5/testdata/validator/starttags.test +375 -0
  118. data/lib/feed_tools/vendor/html5/testdata/validator/style-scoped-attribute.test +7 -0
  119. data/lib/feed_tools/vendor/html5/testdata/validator/tabindexattribute.test +79 -0
  120. data/lib/feed_tools/vendor/html5/tests/preamble.rb +72 -0
  121. data/lib/feed_tools/vendor/html5/tests/test_encoding.rb +35 -0
  122. data/lib/feed_tools/vendor/html5/tests/test_lxp.rb +279 -0
  123. data/lib/feed_tools/vendor/html5/tests/test_parser.rb +68 -0
  124. data/lib/feed_tools/vendor/html5/tests/test_sanitizer.rb +142 -0
  125. data/lib/feed_tools/vendor/html5/tests/test_serializer.rb +68 -0
  126. data/lib/feed_tools/vendor/html5/tests/test_sniffer.rb +27 -0
  127. data/lib/feed_tools/vendor/html5/tests/test_stream.rb +62 -0
  128. data/lib/feed_tools/vendor/html5/tests/test_tokenizer.rb +94 -0
  129. data/lib/feed_tools/vendor/html5/tests/test_treewalkers.rb +135 -0
  130. data/lib/feed_tools/vendor/html5/tests/test_validator.rb +31 -0
  131. data/lib/feed_tools/vendor/html5/tests/tokenizer_test_parser.rb +63 -0
  132. data/lib/feed_tools/vendor/uri.rb +781 -0
  133. data/lib/feed_tools/version.rb +1 -1
  134. data/rakefile +27 -6
  135. data/test/unit/atom_test.rb +298 -210
  136. data/test/unit/helper_test.rb +7 -12
  137. data/test/unit/rdf_test.rb +51 -1
  138. data/test/unit/rss_test.rb +13 -3
  139. metadata +239 -116
  140. data/lib/feed_tools/vendor/htree.rb +0 -97
  141. data/lib/feed_tools/vendor/htree/container.rb +0 -10
  142. data/lib/feed_tools/vendor/htree/context.rb +0 -67
  143. data/lib/feed_tools/vendor/htree/display.rb +0 -27
  144. data/lib/feed_tools/vendor/htree/doc.rb +0 -149
  145. data/lib/feed_tools/vendor/htree/elem.rb +0 -262
  146. data/lib/feed_tools/vendor/htree/encoder.rb +0 -163
  147. data/lib/feed_tools/vendor/htree/equality.rb +0 -218
  148. data/lib/feed_tools/vendor/htree/extract_text.rb +0 -37
  149. data/lib/feed_tools/vendor/htree/fstr.rb +0 -33
  150. data/lib/feed_tools/vendor/htree/gencode.rb +0 -97
  151. data/lib/feed_tools/vendor/htree/htmlinfo.rb +0 -672
  152. data/lib/feed_tools/vendor/htree/inspect.rb +0 -108
  153. data/lib/feed_tools/vendor/htree/leaf.rb +0 -94
  154. data/lib/feed_tools/vendor/htree/loc.rb +0 -367
  155. data/lib/feed_tools/vendor/htree/modules.rb +0 -48
  156. data/lib/feed_tools/vendor/htree/name.rb +0 -124
  157. data/lib/feed_tools/vendor/htree/output.rb +0 -207
  158. data/lib/feed_tools/vendor/htree/parse.rb +0 -409
  159. data/lib/feed_tools/vendor/htree/raw_string.rb +0 -124
  160. data/lib/feed_tools/vendor/htree/regexp-util.rb +0 -15
  161. data/lib/feed_tools/vendor/htree/rexml.rb +0 -130
  162. data/lib/feed_tools/vendor/htree/scan.rb +0 -166
  163. data/lib/feed_tools/vendor/htree/tag.rb +0 -111
  164. data/lib/feed_tools/vendor/htree/template.rb +0 -909
  165. data/lib/feed_tools/vendor/htree/text.rb +0 -115
  166. data/lib/feed_tools/vendor/htree/traverse.rb +0 -465
@@ -37,6 +37,20 @@ module FeedTools
37
37
  @title = nil
38
38
  @id = nil
39
39
  @time = Time.now.gmtime
40
+ @version = FeedTools::FEED_TOOLS_VERSION::STRING
41
+ end
42
+
43
+ # Breaks any references that the feed entry may be keeping around, thus
44
+ # making the job of the garbage collector much, much easier. Call this
45
+ # method prior to feed entries going out of scope to prevent memory leaks.
46
+ def dispose()
47
+ @feed_data = nil
48
+ @feed_data_type = nil
49
+ @xml_document = nil
50
+ @root_node = nil
51
+ @title = nil
52
+ @id = nil
53
+ @time = nil
40
54
  end
41
55
 
42
56
  # Returns the parent feed of this feed item
@@ -69,6 +83,58 @@ module FeedTools
69
83
  return parent_feed
70
84
  end
71
85
 
86
+ # Does a full parse of the feed item.
87
+ def full_parse
88
+ self.configurations
89
+
90
+ self.encoding
91
+ self.xml_document
92
+ self.root_node
93
+
94
+ self.feed_type
95
+ self.feed_version
96
+
97
+ self.id
98
+ self.title
99
+ self.content
100
+ self.summary
101
+ self.links
102
+ self.link
103
+ self.comments
104
+ self.time
105
+ self.updated
106
+ self.published
107
+ self.source
108
+ self.categories
109
+ self.tags
110
+ self.images
111
+ self.rights
112
+ self.author
113
+ self.publisher
114
+
115
+ self.itunes_summary
116
+ self.itunes_subtitle
117
+ self.itunes_image_link
118
+ self.itunes_author
119
+ self.itunes_duration
120
+
121
+ self.media_text
122
+ self.media_thumbnail_link
123
+
124
+ self.explicit?
125
+ end
126
+
127
+ # Returns a duplicate object suitable for serialization
128
+ def serializable
129
+ self.full_parse()
130
+ feed_item_to_dump = self.dup
131
+ feed_item_to_dump.author
132
+ feed_item_to_dump.publisher
133
+ feed_item_to_dump.instance_variable_set("@xml_document", nil)
134
+ feed_item_to_dump.instance_variable_set("@root_node", nil)
135
+ return feed_item_to_dump
136
+ end
137
+
72
138
  # Returns the load options for this feed.
73
139
  def configurations
74
140
  if @configurations.blank?
@@ -90,7 +156,12 @@ module FeedTools
90
156
  # Returns the feed item's encoding.
91
157
  def encoding
92
158
  if @encoding.nil?
93
- @encoding = self.feed.encoding
159
+ parent_feed = self.feed
160
+ if parent_feed != nil
161
+ @encoding = parent_feed.encoding
162
+ else
163
+ @encoding = nil
164
+ end
94
165
  end
95
166
  return @encoding
96
167
  end
@@ -114,14 +185,18 @@ module FeedTools
114
185
  # Sets the feed item's data type.
115
186
  def feed_data_type=(new_feed_data_type)
116
187
  @feed_data_type = new_feed_data_type
188
+ if self.feed_data_type != :xml
189
+ @xml_document = nil
190
+ end
117
191
  end
118
192
 
119
193
  # Returns a REXML Document of the feed_data
120
194
  def xml_document
121
- if self.feed_data_type != :xml
122
- @xml_document = nil
123
- else
124
- if @xml_document.nil?
195
+ if @xml_document.nil?
196
+ return nil if self.feed_data.blank?
197
+ if self.feed_data_type != :xml
198
+ @xml_document = nil
199
+ else
125
200
  # TODO: :ignore_whitespace_nodes => :all
126
201
  # Add that?
127
202
  # ======================================
@@ -131,9 +206,10 @@ module FeedTools
131
206
  return @xml_document
132
207
  end
133
208
 
134
- # Returns the first node within the root_node that matches the xpath query.
209
+ # Returns the first node within the root_node that matches the xpath
210
+ # query.
135
211
  def find_node(xpath, select_result_value=false)
136
- if feed.feed_data_type != :xml
212
+ if self.feed_data_type != :xml
137
213
  raise "The feed data type is not xml."
138
214
  end
139
215
  return FeedTools::XmlHelper.try_xpaths(self.root_node, [xpath],
@@ -142,7 +218,7 @@ module FeedTools
142
218
 
143
219
  # Returns all nodes within the root_node that match the xpath query.
144
220
  def find_all_nodes(xpath, select_result_value=false)
145
- if feed.feed_data_type != :xml
221
+ if self.feed_data_type != :xml
146
222
  raise "The feed data type is not xml."
147
223
  end
148
224
  return FeedTools::XmlHelper.try_xpaths_all(self.root_node, [xpath],
@@ -191,6 +267,10 @@ module FeedTools
191
267
  def id
192
268
  if @id.nil?
193
269
  @id = FeedTools::XmlHelper.try_xpaths(self.root_node, [
270
+ "atom10:id/@gr:original-id",
271
+ "atom03:id/@gr:original-id",
272
+ "atom:id/@gr:original-id",
273
+ "id/@gr:original-id",
194
274
  "atom10:id/text()",
195
275
  "atom03:id/text()",
196
276
  "atom:id/text()",
@@ -215,10 +295,11 @@ module FeedTools
215
295
  "atom03:title",
216
296
  "atom:title",
217
297
  "title",
218
- "dc:title"
298
+ "dc:title",
299
+ "headline"
219
300
  ])
220
301
  @title = FeedTools::HtmlHelper.process_text_construct(title_node,
221
- self.feed_type, self.feed_version)
302
+ self.feed_type, self.feed_version, [self.base_uri])
222
303
  if self.feed_type == "atom" ||
223
304
  self.configurations[:always_strip_wrapper_elements]
224
305
  @title = FeedTools::HtmlHelper.strip_wrapper_element(@title)
@@ -251,6 +332,7 @@ module FeedTools
251
332
  "atom10:content",
252
333
  "atom03:content",
253
334
  "atom:content",
335
+ "body/datacontent",
254
336
  "xhtml:body",
255
337
  "body",
256
338
  "xhtml:div",
@@ -273,18 +355,18 @@ module FeedTools
273
355
  "info"
274
356
  ])
275
357
  @content = FeedTools::HtmlHelper.process_text_construct(content_node,
276
- self.feed_type, self.feed_version)
358
+ self.feed_type, self.feed_version, [self.base_uri])
277
359
  if self.feed_type == "atom" ||
278
360
  self.configurations[:always_strip_wrapper_elements]
279
361
  @content = FeedTools::HtmlHelper.strip_wrapper_element(@content)
280
362
  end
281
- if @content.blank?
363
+ if @content.nil?
282
364
  @content = self.media_text
283
365
  end
284
- if @content.blank?
366
+ if @content.nil?
285
367
  @content = self.itunes_summary
286
368
  end
287
- if @content.blank?
369
+ if @content.nil?
288
370
  @content = self.itunes_subtitle
289
371
  end
290
372
  end
@@ -323,10 +405,11 @@ module FeedTools
323
405
  "atom03:content",
324
406
  "atom:content",
325
407
  "content",
326
- "info"
408
+ "info",
409
+ "body/datacontent"
327
410
  ])
328
411
  @summary = FeedTools::HtmlHelper.process_text_construct(summary_node,
329
- self.feed_type, self.feed_version)
412
+ self.feed_type, self.feed_version, [self.base_uri])
330
413
  if self.feed_type == "atom" ||
331
414
  self.configurations[:always_strip_wrapper_elements]
332
415
  @summary = FeedTools::HtmlHelper.strip_wrapper_element(@summary)
@@ -349,143 +432,6 @@ module FeedTools
349
432
  @summary = new_summary
350
433
  end
351
434
 
352
- # Returns the contents of the itunes:summary element
353
- def itunes_summary
354
- if @itunes_summary.nil?
355
- @itunes_summary = FeedTools::XmlHelper.try_xpaths(self.root_node, [
356
- "itunes:summary/text()"
357
- ], :select_result_value => true)
358
- unless @itunes_summary.blank?
359
- @itunes_summary = FeedTools::HtmlHelper.unescape_entities(@itunes_summary)
360
- @itunes_summary = FeedTools::HtmlHelper.sanitize_html(@itunes_summary)
361
- @itunes_summary.strip!
362
- else
363
- @itunes_summary = nil
364
- end
365
- end
366
- return @itunes_summary
367
- end
368
-
369
- # Sets the contents of the itunes:summary element
370
- def itunes_summary=(new_itunes_summary)
371
- @itunes_summary = new_itunes_summary
372
- end
373
-
374
- # Returns the contents of the itunes:subtitle element
375
- def itunes_subtitle
376
- if @itunes_subtitle.nil?
377
- @itunes_subtitle = FeedTools::XmlHelper.try_xpaths(self.root_node, [
378
- "itunes:subtitle/text()"
379
- ], :select_result_value => true)
380
- unless @itunes_subtitle.blank?
381
- @itunes_subtitle = FeedTools::HtmlHelper.unescape_entities(@itunes_subtitle)
382
- @itunes_subtitle = FeedTools::HtmlHelper.sanitize_html(@itunes_subtitle)
383
- @itunes_subtitle.strip!
384
- else
385
- @itunes_subtitle = nil
386
- end
387
- end
388
- return @itunes_subtitle
389
- end
390
-
391
- # Sets the contents of the itunes:subtitle element
392
- def itunes_subtitle=(new_itunes_subtitle)
393
- @itunes_subtitle = new_itunes_subtitle
394
- end
395
-
396
- # Returns the contents of the media:text element
397
- def media_text
398
- if @media_text.nil?
399
- @media_text = FeedTools::XmlHelper.try_xpaths(self.root_node, [
400
- "media:text/text()"
401
- ], :select_result_value => true)
402
- unless @media_text.blank?
403
- @media_text = FeedTools::HtmlHelper.unescape_entities(@media_text)
404
- @media_text = FeedTools::HtmlHelper.sanitize_html(@media_text)
405
- @media_text.strip!
406
- else
407
- @media_text = nil
408
- end
409
- end
410
- return @media_text
411
- end
412
-
413
- # Sets the contents of the media:text element
414
- def media_text=(new_media_text)
415
- @media_text = new_media_text
416
- end
417
-
418
- # Returns the feed item link
419
- def link
420
- if @link.nil?
421
- max_score = 0
422
- for link_object in self.links.reverse
423
- score = 0
424
- if FeedTools::HtmlHelper.html_type?(link_object.type)
425
- score = score + 2
426
- elsif link_object.type != nil
427
- score = score - 1
428
- end
429
- if FeedTools::HtmlHelper.xml_type?(link_object.type)
430
- score = score + 1
431
- end
432
- if link_object.rel == "alternate"
433
- score = score + 1
434
- end
435
- if link_object.rel == "self"
436
- score = score - 1
437
- end
438
- if score >= max_score
439
- max_score = score
440
- @link = link_object.href
441
- end
442
- end
443
- if @link.blank?
444
- @link = FeedTools::XmlHelper.try_xpaths(self.root_node, [
445
- "@href",
446
- "@rdf:about",
447
- "@about"
448
- ], :select_result_value => true)
449
- end
450
- if @link.blank?
451
- if FeedTools::UriHelper.is_uri?(self.id) &&
452
- (self.id =~ /^http/)
453
- @link = self.id
454
- end
455
- end
456
- if !@link.blank?
457
- @link = FeedTools::HtmlHelper.unescape_entities(@link)
458
- end
459
- @link = self.comments if @link.blank?
460
- @link = nil if @link.blank?
461
- begin
462
- if !(@link =~ /^file:/) &&
463
- !FeedTools::UriHelper.is_uri?(@link)
464
- stored_base_uri =
465
- FeedTools::GenericHelper.recursion_trap(:feed_link) do
466
- self.feed.base_uri if self.feed != nil
467
- end
468
- root_base_uri = nil
469
- unless self.root_node.nil?
470
- root_base_uri = self.root_node.base_uri
471
- end
472
- @link = FeedTools::UriHelper.resolve_relative_uri(
473
- @link, [root_base_uri,stored_base_uri])
474
- end
475
- rescue
476
- end
477
- if self.configurations[:url_normalization_enabled]
478
- @link = FeedTools::UriHelper.normalize_url(@link)
479
- end
480
- end
481
- return @link
482
- end
483
-
484
- # Sets the feed item link
485
- def link=(new_link)
486
- @link = new_link
487
- end
488
-
489
435
  # Returns the links collection
490
436
  def links
491
437
  if @links.nil?
@@ -507,6 +453,7 @@ module FeedTools
507
453
  "@atom03:href",
508
454
  "@atom:href",
509
455
  "@href",
456
+ "@url",
510
457
  "text()"
511
458
  ], :select_result_value => true)
512
459
  if link_object.href.nil? && link_node.base_uri != nil
@@ -517,7 +464,7 @@ module FeedTools
517
464
  !FeedTools::UriHelper.is_uri?(link_object.href)
518
465
  stored_base_uri =
519
466
  FeedTools::GenericHelper.recursion_trap(:feed_link) do
520
- self.feed.base_uri if self.feed != nil
467
+ self.base_uri if self.feed != nil
521
468
  end
522
469
  link_object.href = FeedTools::UriHelper.resolve_relative_uri(
523
470
  link_object.href,
@@ -588,6 +535,15 @@ module FeedTools
588
535
  end
589
536
  @links << link_object
590
537
  end
538
+ if @links.empty? && self.enclosures.size > 0
539
+ # If there's seriously nothing to link to, but there's enclosures
540
+ # available, then add a link to the first one.
541
+ enclosure_link = self.enclosures[0]
542
+ link_object = FeedTools::Link.new
543
+ link_object.href = enclosure_link.url
544
+ link_object.type = enclosure_link.type
545
+ @links << link_object
546
+ end
591
547
  end
592
548
  return @links
593
549
  end
@@ -596,7 +552,193 @@ module FeedTools
596
552
  def links=(new_links)
597
553
  @links = new_links
598
554
  end
599
-
555
+
556
+ # Returns the feed item link
557
+ def link
558
+ if @link.nil?
559
+ max_score = 0
560
+ for link_object in self.links.reverse
561
+ score = 0
562
+ if FeedTools::HtmlHelper.html_type?(link_object.type)
563
+ score = score + 2
564
+ elsif link_object.type != nil
565
+ score = score - 1
566
+ end
567
+ if FeedTools::HtmlHelper.xml_type?(link_object.type)
568
+ score = score + 1
569
+ end
570
+ if link_object.type =~ /^video/ && self.links.size == 1
571
+ score = score + 1
572
+ elsif link_object.type =~ /^audio/ && self.links.size == 1
573
+ score = score + 1
574
+ end
575
+ if link_object.rel == "alternate"
576
+ score = score + 1
577
+ end
578
+ if link_object.rel == "self"
579
+ score = score - 1
580
+ end
581
+ if score >= max_score
582
+ max_score = score
583
+ @link = link_object.href
584
+ end
585
+ end
586
+ if @link.blank?
587
+ @link = FeedTools::XmlHelper.try_xpaths(self.root_node, [
588
+ "@href",
589
+ "@rdf:about",
590
+ "@about"
591
+ ], :select_result_value => true)
592
+ end
593
+ if @link.blank?
594
+ if FeedTools::UriHelper.is_uri?(self.id) &&
595
+ (self.id =~ /^http/)
596
+ @link = self.id
597
+ end
598
+ end
599
+ if !@link.blank?
600
+ @link = FeedTools::HtmlHelper.unescape_entities(@link)
601
+ end
602
+ @link = self.comments if @link.blank?
603
+ @link = nil if @link.blank?
604
+ begin
605
+ if !(@link =~ /^file:/) &&
606
+ !FeedTools::UriHelper.is_uri?(@link)
607
+ stored_base_uri =
608
+ FeedTools::GenericHelper.recursion_trap(:feed_link) do
609
+ self.base_uri if self.feed != nil
610
+ end
611
+ root_base_uri = nil
612
+ unless self.root_node.nil?
613
+ root_base_uri = self.root_node.base_uri
614
+ end
615
+ @link = FeedTools::UriHelper.resolve_relative_uri(
616
+ @link, [root_base_uri,stored_base_uri])
617
+ end
618
+ rescue
619
+ end
620
+ if self.configurations[:url_normalization_enabled]
621
+ @link = FeedTools::UriHelper.normalize_url(@link)
622
+ end
623
+ end
624
+ return @link
625
+ end
626
+
627
+ # Sets the feed item link
628
+ def link=(new_link)
629
+ @link = new_link
630
+ end
631
+
632
+ # Returns the parent feed's base_uri if any.
633
+ def base_uri
634
+ parent_feed = self.feed
635
+ if parent_feed != nil
636
+ return parent_feed.base_uri
637
+ else
638
+ return nil
639
+ end
640
+ end
641
+
642
+ # Returns the url for posting comments
643
+ def comments
644
+ if @comments.nil?
645
+ @comments = FeedTools::XmlHelper.try_xpaths(
646
+ self.root_node, ["comments/text()"],
647
+ :select_result_value => true)
648
+ begin
649
+ if !(@comments =~ /^file:/) &&
650
+ !FeedTools::UriHelper.is_uri?(@comments)
651
+ root_base_uri = nil
652
+ unless self.root_node.nil?
653
+ root_base_uri = self.root_node.base_uri
654
+ end
655
+ @comments = FeedTools::UriHelper.resolve_relative_uri(
656
+ @comments, [root_base_uri, self.base_uri])
657
+ end
658
+ rescue
659
+ end
660
+ if self.configurations[:url_normalization_enabled]
661
+ @comments = FeedTools::UriHelper.normalize_url(@comments)
662
+ end
663
+ end
664
+ return @comments
665
+ end
666
+
667
+ # Sets the url for posting comments
668
+ def comments=(new_comments)
669
+ @comments = new_comments
670
+ end
671
+
672
+ # Returns the contents of the itunes:summary element
673
+ def itunes_summary
674
+ if @itunes_summary.nil?
675
+ @itunes_summary = FeedTools::XmlHelper.try_xpaths(self.root_node, [
676
+ "itunes:summary/text()"
677
+ ], :select_result_value => true)
678
+ unless @itunes_summary.blank?
679
+ @itunes_summary =
680
+ FeedTools::HtmlHelper.unescape_entities(@itunes_summary)
681
+ @itunes_summary =
682
+ FeedTools::HtmlHelper.sanitize_html(@itunes_summary)
683
+ @itunes_summary.strip!
684
+ else
685
+ @itunes_summary = nil
686
+ end
687
+ end
688
+ return @itunes_summary
689
+ end
690
+
691
+ # Sets the contents of the itunes:summary element
692
+ def itunes_summary=(new_itunes_summary)
693
+ @itunes_summary = new_itunes_summary
694
+ end
695
+
696
+ # Returns the contents of the itunes:subtitle element
697
+ def itunes_subtitle
698
+ if @itunes_subtitle.nil?
699
+ @itunes_subtitle = FeedTools::XmlHelper.try_xpaths(self.root_node, [
700
+ "itunes:subtitle/text()"
701
+ ], :select_result_value => true)
702
+ unless @itunes_subtitle.blank?
703
+ @itunes_subtitle =
704
+ FeedTools::HtmlHelper.unescape_entities(@itunes_subtitle)
705
+ @itunes_subtitle =
706
+ FeedTools::HtmlHelper.sanitize_html(@itunes_subtitle)
707
+ @itunes_subtitle.strip!
708
+ else
709
+ @itunes_subtitle = nil
710
+ end
711
+ end
712
+ return @itunes_subtitle
713
+ end
714
+
715
+ # Sets the contents of the itunes:subtitle element
716
+ def itunes_subtitle=(new_itunes_subtitle)
717
+ @itunes_subtitle = new_itunes_subtitle
718
+ end
719
+
720
+ # Returns the contents of the media:text element
721
+ def media_text
722
+ if @media_text.nil?
723
+ @media_text = FeedTools::XmlHelper.try_xpaths(self.root_node, [
724
+ "media:text/text()"
725
+ ], :select_result_value => true)
726
+ unless @media_text.blank?
727
+ @media_text = FeedTools::HtmlHelper.unescape_entities(@media_text)
728
+ @media_text = FeedTools::HtmlHelper.sanitize_html(@media_text)
729
+ @media_text.strip!
730
+ else
731
+ @media_text = nil
732
+ end
733
+ end
734
+ return @media_text
735
+ end
736
+
737
+ # Sets the contents of the media:text element
738
+ def media_text=(new_media_text)
739
+ @media_text = new_media_text
740
+ end
741
+
600
742
  # Returns a list of the feed item's categories
601
743
  def categories
602
744
  if @categories.nil?
@@ -607,16 +749,19 @@ module FeedTools
607
749
  ])
608
750
  for category_node in category_nodes
609
751
  category = FeedTools::Category.new
610
- category.term = FeedTools::XmlHelper.try_xpaths(category_node, ["@term", "text()"],
752
+ category.term = FeedTools::XmlHelper.try_xpaths(
753
+ category_node, ["@term", "text()"],
611
754
  :select_result_value => true)
612
755
  category.term.strip! unless category.term.nil?
613
- category.label = FeedTools::XmlHelper.try_xpaths(category_node, ["@label"],
756
+ category.label = FeedTools::XmlHelper.try_xpaths(
757
+ category_node, ["@label"],
614
758
  :select_result_value => true)
615
759
  category.label.strip! unless category.label.nil?
616
- category.scheme = FeedTools::XmlHelper.try_xpaths(category_node, [
617
- "@scheme",
618
- "@domain"
619
- ], :select_result_value => true)
760
+ category.scheme = FeedTools::XmlHelper.try_xpaths(
761
+ category_node, [
762
+ "@scheme",
763
+ "@domain"
764
+ ], :select_result_value => true)
620
765
  category.scheme.strip! unless category.scheme.nil?
621
766
  @categories << category
622
767
  end
@@ -641,6 +786,7 @@ module FeedTools
641
786
  "url/text()",
642
787
  "@rdf:resource",
643
788
  "@href",
789
+ "@url",
644
790
  "text()"
645
791
  ], :select_result_value => true)
646
792
  if image.href.nil? && image_node.base_uri != nil
@@ -651,7 +797,7 @@ module FeedTools
651
797
  !FeedTools::UriHelper.is_uri?(image.href)
652
798
  stored_base_uri =
653
799
  FeedTools::GenericHelper.recursion_trap(:feed_link) do
654
- self.feed.base_uri if self.feed != nil
800
+ self.base_uri if self.feed != nil
655
801
  end
656
802
  image.href = FeedTools::UriHelper.resolve_relative_uri(
657
803
  image.href, [image_node.base_uri, stored_base_uri])
@@ -707,7 +853,8 @@ module FeedTools
707
853
  "itunes:link[@rel='image']/@href"
708
854
  ], :select_result_value => true)
709
855
  if self.configurations[:url_normalization_enabled]
710
- @itunes_image_link = FeedTools::UriHelper.normalize_url(@itunes_image_link)
856
+ @itunes_image_link =
857
+ FeedTools::UriHelper.normalize_url(@itunes_image_link)
711
858
  end
712
859
  end
713
860
  return @itunes_image_link
@@ -721,11 +868,13 @@ module FeedTools
721
868
  # Returns the feed item media thumbnail link
722
869
  def media_thumbnail_link
723
870
  if @media_thumbnail_link.nil?
724
- @media_thumbnail_link = FeedTools::XmlHelper.try_xpaths(self.root_node, [
725
- "media:thumbnail/@url"
726
- ], :select_result_value => true)
871
+ @media_thumbnail_link = FeedTools::XmlHelper.try_xpaths(
872
+ self.root_node, [
873
+ "media:thumbnail/@url"
874
+ ], :select_result_value => true)
727
875
  if self.configurations[:url_normalization_enabled]
728
- @media_thumbnail_link = FeedTools::UriHelper.normalize_url(@media_thumbnail_link)
876
+ @media_thumbnail_link =
877
+ FeedTools::UriHelper.normalize_url(@media_thumbnail_link)
729
878
  end
730
879
  end
731
880
  return @media_thumbnail_link
@@ -750,7 +899,7 @@ module FeedTools
750
899
  "rights"
751
900
  ])
752
901
  @rights = FeedTools::HtmlHelper.process_text_construct(rights_node,
753
- self.feed_type, self.feed_version)
902
+ self.feed_type, self.feed_version, [self.base_uri])
754
903
  if self.feed_type == "atom" ||
755
904
  self.configurations[:always_strip_wrapper_elements]
756
905
  @rights = FeedTools::HtmlHelper.strip_wrapper_element(@rights)
@@ -764,12 +913,24 @@ module FeedTools
764
913
  @rights = new_rights
765
914
  end
766
915
 
767
- def license #:nodoc:
768
- raise "Not implemented yet."
916
+ # Returns the first license link for the feed item.
917
+ def license
918
+ return self.licenses.first
919
+ end
920
+
921
+ # Returns all licenses linked from this feed item.
922
+ def licenses
923
+ if @licenses.nil?
924
+ @licenses = self.links.select do |link|
925
+ link.rel == "license"
926
+ end
927
+ end
928
+ return @licenses
769
929
  end
770
930
 
771
- def license=(new_license) #:nodoc:
772
- raise "Not implemented yet."
931
+ # Sets the feed item's licenses.
932
+ def licenses=(new_licenses)
933
+ @licenses = new_licenses
773
934
  end
774
935
 
775
936
  # Returns all feed item enclosures
@@ -793,6 +954,9 @@ module FeedTools
793
954
  media_group_enclosures =
794
955
  FeedTools::XmlHelper.try_xpaths_all(self.root_node, ["media:group"])
795
956
 
957
+ bogus_enclosures =
958
+ FeedTools::XmlHelper.try_xpaths_all(self.root_node, ["video"])
959
+
796
960
  # TODO: Implement this
797
961
  bittorrent_enclosures =
798
962
  FeedTools::XmlHelper.try_xpaths_all(self.root_node,
@@ -839,6 +1003,33 @@ module FeedTools
839
1003
  @enclosures << enclosure
840
1004
  end
841
1005
  end
1006
+
1007
+ # Parse atom-type enclosures. If there are repeats of the same
1008
+ # enclosure object, we merge the two together.
1009
+ for enclosure_node in bogus_enclosures
1010
+ enclosure_url = FeedTools::HtmlHelper.unescape_entities(
1011
+ enclosure_node.attributes["url"].to_s)
1012
+ enclosure = nil
1013
+ new_enclosure = false
1014
+ for existing_enclosure in @enclosures
1015
+ if existing_enclosure.url == enclosure_url
1016
+ enclosure = existing_enclosure
1017
+ break
1018
+ end
1019
+ end
1020
+ if enclosure.nil?
1021
+ new_enclosure = true
1022
+ enclosure = FeedTools::Enclosure.new
1023
+ end
1024
+ enclosure.url = enclosure_url
1025
+ if File.extname(enclosure_url) == ".wmv"
1026
+ enclosure.type = "video/x-ms-wmv"
1027
+ end
1028
+ enclosure.explicit = false
1029
+ if new_enclosure
1030
+ @enclosures << enclosure
1031
+ end
1032
+ end
842
1033
 
843
1034
  # Creates an anonymous method to parse content objects from the media
844
1035
  # module. We do this to avoid excessive duplication of code since we
@@ -873,21 +1064,26 @@ module FeedTools
873
1064
  enclosure_node.attributes["expression"].to_s
874
1065
  enclosure.is_default =
875
1066
  (enclosure_node.attributes["isDefault"].to_s.downcase == "true")
876
- enclosure_thumbnail_url = FeedTools::XmlHelper.try_xpaths(enclosure_node,
877
- ["media:thumbnail/@url"], :select_result_value => true)
1067
+ enclosure_thumbnail_url =
1068
+ FeedTools::XmlHelper.try_xpaths(enclosure_node,
1069
+ ["media:thumbnail/@url"], :select_result_value => true)
878
1070
  if !enclosure_thumbnail_url.blank?
879
1071
  enclosure.thumbnail = FeedTools::EnclosureThumbnail.new(
880
- FeedTools::HtmlHelper.unescape_entities(enclosure_thumbnail_url),
881
1072
  FeedTools::HtmlHelper.unescape_entities(
882
- FeedTools::XmlHelper.try_xpaths(enclosure_node, ["media:thumbnail/@height"],
1073
+ enclosure_thumbnail_url),
1074
+ FeedTools::HtmlHelper.unescape_entities(
1075
+ FeedTools::XmlHelper.try_xpaths(enclosure_node,
1076
+ ["media:thumbnail/@height"],
883
1077
  :select_result_value => true)),
884
1078
  FeedTools::HtmlHelper.unescape_entities(
885
- FeedTools::XmlHelper.try_xpaths(enclosure_node, ["media:thumbnail/@width"],
1079
+ FeedTools::XmlHelper.try_xpaths(enclosure_node,
1080
+ ["media:thumbnail/@width"],
886
1081
  :select_result_value => true))
887
1082
  )
888
1083
  end
889
1084
  enclosure.categories = []
890
- for category in FeedTools::XmlHelper.try_xpaths_all(enclosure_node, ["media:category"])
1085
+ for category in FeedTools::XmlHelper.try_xpaths_all(
1086
+ enclosure_node, ["media:category"])
891
1087
  enclosure.categories << FeedTools::Category.new
892
1088
  enclosure.categories.last.term =
893
1089
  FeedTools::HtmlHelper.unescape_entities(category.inner_xml)
@@ -904,20 +1100,24 @@ module FeedTools
904
1100
  enclosure.categories.last.label = nil
905
1101
  end
906
1102
  end
907
- enclosure_media_hash = FeedTools::XmlHelper.try_xpaths(enclosure_node,
908
- ["media:hash/text()"], :select_result_value => true)
1103
+ enclosure_media_hash =
1104
+ FeedTools::XmlHelper.try_xpaths(enclosure_node,
1105
+ ["media:hash/text()"], :select_result_value => true)
909
1106
  if !enclosure_media_hash.nil?
910
1107
  enclosure.hash = FeedTools::EnclosureHash.new(
911
- FeedTools::HtmlHelper.sanitize_html(FeedTools::HtmlHelper.unescape_entities(
912
- enclosure_media_hash), :strip),
1108
+ FeedTools::HtmlHelper.sanitize_html(
1109
+ FeedTools::HtmlHelper.unescape_entities(
1110
+ enclosure_media_hash), :strip),
913
1111
  "md5"
914
1112
  )
915
1113
  end
916
- enclosure_media_player_url = FeedTools::XmlHelper.try_xpaths(enclosure_node,
917
- ["media:player/@url"], :select_result_value => true)
1114
+ enclosure_media_player_url =
1115
+ FeedTools::XmlHelper.try_xpaths(enclosure_node,
1116
+ ["media:player/@url"], :select_result_value => true)
918
1117
  if !enclosure_media_player_url.blank?
919
1118
  enclosure.player = FeedTools::EnclosurePlayer.new(
920
- FeedTools::HtmlHelper.unescape_entities(enclosure_media_player_url),
1119
+ FeedTools::HtmlHelper.unescape_entities(
1120
+ enclosure_media_player_url),
921
1121
  FeedTools::HtmlHelper.unescape_entities(
922
1122
  FeedTools::XmlHelper.try_xpaths(enclosure_node,
923
1123
  ["media:player/@height"], :select_result_value => true)),
@@ -927,9 +1127,11 @@ module FeedTools
927
1127
  )
928
1128
  end
929
1129
  enclosure.credits = []
930
- for credit in FeedTools::XmlHelper.try_xpaths_all(enclosure_node, ["media:credit"])
1130
+ for credit in FeedTools::XmlHelper.try_xpaths_all(
1131
+ enclosure_node, ["media:credit"])
931
1132
  enclosure.credits << FeedTools::EnclosureCredit.new(
932
- FeedTools::HtmlHelper.unescape_entities(credit.inner_xml.to_s.strip),
1133
+ FeedTools::HtmlHelper.unescape_entities(
1134
+ credit.inner_xml.to_s.strip),
933
1135
  FeedTools::HtmlHelper.unescape_entities(
934
1136
  credit.attributes["role"].to_s.downcase)
935
1137
  )
@@ -940,10 +1142,12 @@ module FeedTools
940
1142
  enclosure.credits.last.role = nil
941
1143
  end
942
1144
  end
943
- enclosure.explicit = (FeedTools::XmlHelper.try_xpaths(enclosure_node,
944
- ["media:adult/text()"]).to_s.downcase == "true")
1145
+ enclosure.explicit =
1146
+ (FeedTools::XmlHelper.try_xpaths(enclosure_node,
1147
+ ["media:adult/text()"]).to_s.downcase == "true")
945
1148
  enclosure_media_text =
946
- FeedTools::XmlHelper.try_xpaths(enclosure_node, ["media:text/text()"])
1149
+ FeedTools::XmlHelper.try_xpaths(enclosure_node,
1150
+ ["media:text/text()"])
947
1151
  if !enclosure_media_text.blank?
948
1152
  enclosure.text = FeedTools::HtmlHelper.unescape_entities(
949
1153
  enclosure_media_text)
@@ -964,7 +1168,8 @@ module FeedTools
964
1168
  # Parse the group objects.
965
1169
  for media_group in media_group_enclosures
966
1170
  group_media_content_enclosures =
967
- FeedTools::XmlHelper.try_xpaths_all(media_group, ["media:content"])
1171
+ FeedTools::XmlHelper.try_xpaths_all(media_group,
1172
+ ["media:content"])
968
1173
 
969
1174
  # Parse the content objects within the group objects.
970
1175
  affected_enclosures =
@@ -973,23 +1178,27 @@ module FeedTools
973
1178
  # Now make sure that content objects inherit certain properties from
974
1179
  # the group objects.
975
1180
  for enclosure in affected_enclosures
976
- media_group_thumbnail = FeedTools::XmlHelper.try_xpaths(media_group,
977
- ["media:thumbnail/@url"], :select_result_value => true)
1181
+ media_group_thumbnail =
1182
+ FeedTools::XmlHelper.try_xpaths(media_group,
1183
+ ["media:thumbnail/@url"], :select_result_value => true)
978
1184
  if enclosure.thumbnail.nil? && !media_group_thumbnail.blank?
979
1185
  enclosure.thumbnail = FeedTools::EnclosureThumbnail.new(
980
1186
  FeedTools::HtmlHelper.unescape_entities(
981
1187
  media_group_thumbnail),
982
1188
  FeedTools::HtmlHelper.unescape_entities(
983
- FeedTools::XmlHelper.try_xpaths(media_group, ["media:thumbnail/@height"],
1189
+ FeedTools::XmlHelper.try_xpaths(media_group,
1190
+ ["media:thumbnail/@height"],
984
1191
  :select_result_value => true)),
985
1192
  FeedTools::HtmlHelper.unescape_entities(
986
- FeedTools::XmlHelper.try_xpaths(media_group, ["media:thumbnail/@width"],
1193
+ FeedTools::XmlHelper.try_xpaths(media_group,
1194
+ ["media:thumbnail/@width"],
987
1195
  :select_result_value => true))
988
1196
  )
989
1197
  end
990
1198
  if (enclosure.categories.blank?)
991
1199
  enclosure.categories = []
992
- for category in FeedTools::XmlHelper.try_xpaths_all(media_group, ["media:category"])
1200
+ for category in FeedTools::XmlHelper.try_xpaths_all(
1201
+ media_group, ["media:category"])
993
1202
  enclosure.categories << FeedTools::Category.new
994
1203
  enclosure.categories.last.term =
995
1204
  FeedTools::HtmlHelper.unescape_entities(category.inner_xml)
@@ -1007,31 +1216,42 @@ module FeedTools
1007
1216
  end
1008
1217
  end
1009
1218
  end
1010
- enclosure_media_group_hash = FeedTools::XmlHelper.try_xpaths(enclosure_node,
1011
- ["media:hash/text()"], :select_result_value => true)
1219
+ enclosure_media_group_hash =
1220
+ FeedTools::XmlHelper.try_xpaths(enclosure_node,
1221
+ ["media:hash/text()"], :select_result_value => true)
1012
1222
  if enclosure.hash.nil? && !enclosure_media_group_hash.blank?
1013
1223
  enclosure.hash = FeedTools::EnclosureHash.new(
1014
- FeedTools::HtmlHelper.sanitize_html(FeedTools::HtmlHelper.unescape_entities(
1015
- enclosure_media_group_hash), :strip),
1224
+ FeedTools::HtmlHelper.sanitize_html(
1225
+ FeedTools::HtmlHelper.unescape_entities(
1226
+ enclosure_media_group_hash), :strip),
1016
1227
  "md5"
1017
1228
  )
1018
1229
  end
1019
- enclosure_media_group_url = FeedTools::XmlHelper.try_xpaths(media_group,
1020
- "media:player/@url", :select_result_value => true)
1230
+ enclosure_media_group_url = FeedTools::XmlHelper.try_xpaths(
1231
+ media_group,
1232
+ "media:player/@url",
1233
+ :select_result_value => true
1234
+ )
1021
1235
  if enclosure.player.nil? && !enclosure_media_group_url.blank?
1022
1236
  enclosure.player = FeedTools::EnclosurePlayer.new(
1023
- FeedTools::HtmlHelper.unescape_entities(enclosure_media_group_url),
1024
1237
  FeedTools::HtmlHelper.unescape_entities(
1025
- FeedTools::XmlHelper.try_xpaths(media_group, ["media:player/@height"],
1238
+ enclosure_media_group_url),
1239
+ FeedTools::HtmlHelper.unescape_entities(
1240
+ FeedTools::XmlHelper.try_xpaths(media_group,
1241
+ ["media:player/@height"],
1026
1242
  :select_result_value => true)),
1027
1243
  FeedTools::HtmlHelper.unescape_entities(
1028
- FeedTools::XmlHelper.try_xpaths(media_group, ["media:player/@width"],
1029
- :select_result_value => true))
1244
+ FeedTools::XmlHelper.try_xpaths(media_group,
1245
+ ["media:player/@width"],
1246
+ :select_result_value => true
1247
+ )
1248
+ )
1030
1249
  )
1031
1250
  end
1032
1251
  if enclosure.credits.nil? || enclosure.credits.size == 0
1033
1252
  enclosure.credits = []
1034
- for credit in FeedTools::XmlHelper.try_xpaths_all(media_group, ["media:credit"])
1253
+ for credit in FeedTools::XmlHelper.try_xpaths_all(
1254
+ media_group, ["media:credit"])
1035
1255
  enclosure.credits << FeedTools::EnclosureCredit.new(
1036
1256
  FeedTools::HtmlHelper.unescape_entities(credit.inner_xml),
1037
1257
  FeedTools::HtmlHelper.unescape_entities(
@@ -1043,13 +1263,15 @@ module FeedTools
1043
1263
  end
1044
1264
  end
1045
1265
  if enclosure.explicit?.nil?
1046
- enclosure.explicit = ((FeedTools::XmlHelper.try_xpaths(media_group, [
1047
- "media:adult/text()"
1048
- ], :select_result_value => true).downcase == "true") ?
1049
- true : false)
1266
+ enclosure.explicit =
1267
+ ((FeedTools::XmlHelper.try_xpaths(media_group, [
1268
+ "media:adult/text()"
1269
+ ], :select_result_value => true).downcase == "true") ?
1270
+ true : false)
1050
1271
  end
1051
- enclosure_media_group_text = FeedTools::XmlHelper.try_xpaths(media_group,
1052
- ["media:text/text()"], :select_result_value => true)
1272
+ enclosure_media_group_text =
1273
+ FeedTools::XmlHelper.try_xpaths(media_group,
1274
+ ["media:text/text()"], :select_result_value => true)
1053
1275
  if enclosure.text.nil? && !enclosure_media_group_text.blank?
1054
1276
  enclosure.text = FeedTools::HtmlHelper.sanitize_html(
1055
1277
  FeedTools::HtmlHelper.unescape_entities(
@@ -1070,12 +1292,14 @@ module FeedTools
1070
1292
 
1071
1293
  # Add all the itunes categories
1072
1294
  itunes_categories =
1073
- FeedTools::XmlHelper.try_xpaths_all(self.root_node, ["itunes:category"])
1295
+ FeedTools::XmlHelper.try_xpaths_all(self.root_node,
1296
+ ["itunes:category"])
1074
1297
  for itunes_category in itunes_categories
1075
1298
  genre = "Podcasts"
1076
1299
  category = itunes_category.attributes["text"].to_s
1077
1300
  subcategory =
1078
- FeedTools::XmlHelper.try_xpaths(itunes_category, ["itunes:category/@text"],
1301
+ FeedTools::XmlHelper.try_xpaths(itunes_category,
1302
+ ["itunes:category/@text"],
1079
1303
  :select_result_value => true)
1080
1304
  category_path = genre
1081
1305
  if !category.blank?
@@ -1136,6 +1360,14 @@ module FeedTools
1136
1360
  unless enclosure.categories.nil?
1137
1361
  enclosure.categories.uniq!
1138
1362
  end
1363
+
1364
+ # Normalize enclosure URIs
1365
+ if !enclosure.href.blank?
1366
+ enclosure.href =
1367
+ FeedTools::UriHelper.normalize_url(enclosure.href)
1368
+ else
1369
+ enclosure.href = nil
1370
+ end
1139
1371
  end
1140
1372
 
1141
1373
  # And finally, now things get complicated. This is where we make
@@ -1302,6 +1534,12 @@ module FeedTools
1302
1534
  rescue
1303
1535
  end
1304
1536
  end
1537
+ if FeedTools::XmlHelper.try_xpaths(author_node,
1538
+ ["@gr:unknown-author"], :select_result_value => true) == "true"
1539
+ if @author.name == "(author unknown)"
1540
+ @author.name = nil
1541
+ end
1542
+ end
1305
1543
  end
1306
1544
  # Fallback on the itunes module if we didn't find an author name
1307
1545
  begin
@@ -1309,6 +1547,13 @@ module FeedTools
1309
1547
  rescue
1310
1548
  @author.name = nil
1311
1549
  end
1550
+ if @author.name.blank? && @author.email.blank? &&
1551
+ @author.href.blank?
1552
+ parent_feed = self.feed
1553
+ if parent_feed != nil
1554
+ @author = parent_feed.author.dup
1555
+ end
1556
+ end
1312
1557
  end
1313
1558
  return @author
1314
1559
  end
@@ -1392,6 +1637,13 @@ module FeedTools
1392
1637
  rescue
1393
1638
  end
1394
1639
  end
1640
+ if @publisher.name.blank? && @publisher.email.blank? &&
1641
+ @publisher.href.blank?
1642
+ parent_feed = self.feed
1643
+ if parent_feed != nil
1644
+ @publisher = parent_feed.publisher.dup
1645
+ end
1646
+ end
1395
1647
  end
1396
1648
  return @publisher
1397
1649
  end
@@ -1422,7 +1674,12 @@ module FeedTools
1422
1674
  @itunes_author = FeedTools::HtmlHelper.unescape_entities(
1423
1675
  FeedTools::XmlHelper.try_xpaths(self.root_node,
1424
1676
  ["itunes:author/text()"], :select_result_value => true))
1425
- @itunes_author = feed.itunes_author if @itunes_author.blank?
1677
+ if @itunes_author.blank?
1678
+ parent_feed = self.feed
1679
+ if parent_feed != nil
1680
+ @itunes_author = parent_feed.itunes_author
1681
+ end
1682
+ end
1426
1683
  end
1427
1684
  return @itunes_author
1428
1685
  end
@@ -1484,7 +1741,8 @@ module FeedTools
1484
1741
  "published/text()",
1485
1742
  "dc:date/text()",
1486
1743
  "pubDate/text()",
1487
- "date/text()"
1744
+ "date/text()",
1745
+ "lastupdated/text()"
1488
1746
  ], :select_result_value => true)
1489
1747
  begin
1490
1748
  if !time_string.blank?
@@ -1585,7 +1843,8 @@ module FeedTools
1585
1843
  "atom03:modified/text()",
1586
1844
  "atom:modified/text()",
1587
1845
  "modified/text()",
1588
- "lastBuildDate/text()"
1846
+ "lastBuildDate/text()",
1847
+ "lastupdated/text()"
1589
1848
  ], :select_result_value => true)
1590
1849
  if !updated_string.blank?
1591
1850
  @updated = Time.parse(updated_string).gmtime rescue nil
@@ -1630,36 +1889,8 @@ module FeedTools
1630
1889
  def published=(new_published)
1631
1890
  @published = new_published
1632
1891
  end
1633
-
1634
- # Returns the url for posting comments
1635
- def comments
1636
- if @comments.nil?
1637
- @comments = FeedTools::XmlHelper.try_xpaths(self.root_node, ["comments/text()"],
1638
- :select_result_value => true)
1639
- begin
1640
- if !(@comments =~ /^file:/) &&
1641
- !FeedTools::UriHelper.is_uri?(@comments)
1642
- root_base_uri = nil
1643
- unless self.root_node.nil?
1644
- root_base_uri = self.root_node.base_uri
1645
- end
1646
- @comments = FeedTools::UriHelper.resolve_relative_uri(
1647
- @comments, [root_base_uri, self.base_uri])
1648
- end
1649
- rescue
1650
- end
1651
- if self.configurations[:url_normalization_enabled]
1652
- @comments = FeedTools::UriHelper.normalize_url(@comments)
1653
- end
1654
- end
1655
- return @comments
1656
- end
1657
-
1658
- # Sets the url for posting comments
1659
- def comments=(new_comments)
1660
- @comments = new_comments
1661
- end
1662
1892
 
1893
+ # TODO: FIX ME! This code is completely wrong.
1663
1894
  # The source that this post was based on
1664
1895
  def source
1665
1896
  if @source.nil?
@@ -1702,7 +1933,8 @@ module FeedTools
1702
1933
  if rdf_bag != nil && rdf_bag.size > 0
1703
1934
  for tag_node in rdf_bag
1704
1935
  begin
1705
- tag_url = FeedTools::XmlHelper.try_xpaths(tag_node, ["@resource"],
1936
+ tag_url = FeedTools::XmlHelper.try_xpaths(tag_node,
1937
+ ["@resource"],
1706
1938
  :select_result_value => true)
1707
1939
  tag_match = tag_url.scan(/\/(tag|tags)\/(\w+)$/)
1708
1940
  if tag_match.size > 0
@@ -1715,7 +1947,8 @@ module FeedTools
1715
1947
  end
1716
1948
  if @tags.nil? || @tags.size == 0
1717
1949
  @tags = []
1718
- tag_list = FeedTools::XmlHelper.try_xpaths_all(self.root_node, ["category/text()"],
1950
+ tag_list = FeedTools::XmlHelper.try_xpaths_all(self.root_node,
1951
+ ["category/text()"],
1719
1952
  :select_result_value => true)
1720
1953
  for tag in tag_list
1721
1954
  @tags << tag.to_s.downcase.strip
@@ -1723,7 +1956,8 @@ module FeedTools
1723
1956
  end
1724
1957
  if @tags.nil? || @tags.size == 0
1725
1958
  @tags = []
1726
- tag_list = FeedTools::XmlHelper.try_xpaths_all(self.root_node, ["dc:subject/text()"],
1959
+ tag_list = FeedTools::XmlHelper.try_xpaths_all(self.root_node,
1960
+ ["dc:subject/text()"],
1727
1961
  :select_result_value => true)
1728
1962
  for tag in tag_list
1729
1963
  @tags << tag.to_s.downcase.strip
@@ -1731,9 +1965,10 @@ module FeedTools
1731
1965
  end
1732
1966
  if @tags.blank?
1733
1967
  begin
1734
- itunes_keywords_string = FeedTools::XmlHelper.try_xpaths(self.root_node, [
1735
- "itunes:keywords/text()"
1736
- ], :select_result_value => true)
1968
+ itunes_keywords_string =
1969
+ FeedTools::XmlHelper.try_xpaths(self.root_node, [
1970
+ "itunes:keywords/text()"
1971
+ ], :select_result_value => true)
1737
1972
  unless itunes_keywords_string.blank?
1738
1973
  @tags = itunes_keywords_string.downcase.split(",")
1739
1974
  if @tags.size == 1
@@ -1771,8 +2006,10 @@ module FeedTools
1771
2006
  "media:adult/text()",
1772
2007
  "itunes:explicit/text()"
1773
2008
  ], :select_result_value => true)
1774
- if explicit_string == "true" || explicit_string == "yes" ||
1775
- feed.explicit?
2009
+ parent_feed = self.feed
2010
+ if explicit_string == "true" || explicit_string == "yes"
2011
+ @explicit = true
2012
+ elsif parent_feed != nil && parent_feed.explicit?
1776
2013
  @explicit = true
1777
2014
  else
1778
2015
  @explicit = false
@@ -1786,8 +2023,9 @@ module FeedTools
1786
2023
  @explicit = (new_explicit ? true : false)
1787
2024
  end
1788
2025
 
1789
- # A hook method that is called during the feed generation process. Overriding this method
1790
- # will enable additional content to be inserted into the feed.
2026
+ # A hook method that is called during the feed generation process.
2027
+ # Overriding this method will enable additional content to be inserted
2028
+ # into the feed.
1791
2029
  def build_xml_hook(feed_type, version, xml_builder)
1792
2030
  return nil
1793
2031
  end
@@ -1796,20 +2034,41 @@ module FeedTools
1796
2034
  def build_xml(feed_type=(self.feed.feed_type or "atom"), version=nil,
1797
2035
  xml_builder=Builder::XmlMarkup.new(
1798
2036
  :indent => 2, :escape_attrs => false))
2037
+
2038
+ parent_feed = self.feed
2039
+ if parent_feed.find_node(
2040
+ "access:restriction/@relationship").to_s == "deny"
2041
+ raise StandardError,
2042
+ "Operation not permitted. This feed denies redistribution."
2043
+ elsif parent_feed.find_node("@indexing:index").to_s == "no"
2044
+ raise StandardError,
2045
+ "Operation not permitted. This feed denies redistribution."
2046
+ end
2047
+ if self.find_node(
2048
+ "access:restriction/@relationship").to_s == "deny"
2049
+ raise StandardError,
2050
+ "Operation not permitted. This feed item denies redistribution."
2051
+ end
2052
+
2053
+ self.full_parse()
2054
+
1799
2055
  if feed_type == "rss" && (version == nil || version == 0.0)
1800
2056
  version = 1.0
1801
2057
  elsif feed_type == "atom" && (version == nil || version == 0.0)
1802
2058
  version = 1.0
1803
2059
  end
1804
- if feed_type == "rss" && (version == 0.9 || version == 1.0 || version == 1.1)
2060
+ if feed_type == "rss" &&
2061
+ (version == 0.9 || version == 1.0 || version == 1.1)
1805
2062
  # RDF-based rss format
1806
2063
  if link.nil?
1807
- raise "Cannot generate an rdf-based feed item with a nil link field."
2064
+ raise "Cannot generate an rdf-based feed item with a " +
2065
+ "nil link field."
1808
2066
  end
1809
2067
  return xml_builder.item("rdf:about" =>
1810
2068
  FeedTools::HtmlHelper.escape_entities(link)) do
1811
2069
  unless self.title.blank?
1812
- xml_builder.title(FeedTools::HtmlHelper.strip_html_tags(self.title))
2070
+ xml_builder.title(
2071
+ FeedTools::HtmlHelper.strip_html_tags(self.title))
1813
2072
  else
1814
2073
  xml_builder.title
1815
2074
  end
@@ -1851,7 +2110,8 @@ module FeedTools
1851
2110
  # normal rss format
1852
2111
  return xml_builder.item do
1853
2112
  unless self.title.blank?
1854
- xml_builder.title(FeedTools::HtmlHelper.strip_html_tags(self.title))
2113
+ xml_builder.title(
2114
+ FeedTools::HtmlHelper.strip_html_tags(self.title))
1855
2115
  end
1856
2116
  unless self.link.blank?
1857
2117
  xml_builder.link(self.link)
@@ -1876,11 +2136,12 @@ module FeedTools
1876
2136
  elsif !self.time.nil?
1877
2137
  xml_builder.pubDate(self.time.rfc822)
1878
2138
  end
1879
- unless self.copyright.blank?
1880
- xml_builder.tag!("dc:rights", self.copyright)
2139
+ unless self.rights.blank?
2140
+ xml_builder.tag!("dc:rights", self.rights)
1881
2141
  end
1882
2142
  unless self.guid.blank?
1883
- if FeedTools::UriHelper.is_uri?(self.guid) && (self.guid =~ /^http/)
2143
+ if FeedTools::UriHelper.is_uri?(self.guid) &&
2144
+ (self.guid =~ /^http/)
1884
2145
  xml_builder.guid(self.guid, "isPermaLink" => "true")
1885
2146
  else
1886
2147
  xml_builder.guid(self.guid, "isPermaLink" => "false")
@@ -1919,7 +2180,8 @@ module FeedTools
1919
2180
  end
1920
2181
  rescue
1921
2182
  end
1922
- attribute_hash["url"] = FeedTools::UriHelper.normalize_url(enclosure.url)
2183
+ attribute_hash["url"] =
2184
+ FeedTools::UriHelper.normalize_url(enclosure.url)
1923
2185
  if enclosure.type != nil
1924
2186
  attribute_hash["type"] = enclosure.type
1925
2187
  end
@@ -1993,7 +2255,8 @@ module FeedTools
1993
2255
  if self.id != nil
1994
2256
  unless FeedTools::UriHelper.is_uri? self.id
1995
2257
  if self.time != nil && self.link != nil
1996
- xml_builder.id(FeedTools::UriHelper.build_tag_uri(self.link, self.time))
2258
+ xml_builder.id(FeedTools::UriHelper.build_tag_uri(
2259
+ self.link, self.time))
1997
2260
  elsif self.link != nil
1998
2261
  xml_builder.id(FeedTools.build_urn_uuid_uri(self.link))
1999
2262
  else
@@ -2004,7 +2267,8 @@ module FeedTools
2004
2267
  xml_builder.id(self.id)
2005
2268
  end
2006
2269
  elsif self.time != nil && self.link != nil
2007
- xml_builder.id(FeedTools::UriHelper.build_tag_uri(self.link, self.time))
2270
+ xml_builder.id(FeedTools::UriHelper.build_tag_uri(
2271
+ self.link, self.time))
2008
2272
  else
2009
2273
  raise "Cannot build feed, missing feed unique id."
2010
2274
  end
@@ -2018,7 +2282,8 @@ module FeedTools
2018
2282
  attribute_hash = {}
2019
2283
  next if enclosure.url.blank?
2020
2284
  attribute_hash["rel"] = "enclosure"
2021
- attribute_hash["href"] = FeedTools::UriHelper.normalize_url(enclosure.url)
2285
+ attribute_hash["href"] =
2286
+ FeedTools::UriHelper.normalize_url(enclosure.url)
2022
2287
  if enclosure.type != nil
2023
2288
  attribute_hash["type"] = enclosure.type
2024
2289
  end