feedtools 0.2.26 → 0.2.27

Sign up to get free protection for your applications and to get access to all the features.
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