whistle 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/History.txt +3 -0
  2. data/README.txt +38 -0
  3. data/bin/whistle +90 -0
  4. data/lib/config.rb +19 -0
  5. data/lib/phash.rb +16 -0
  6. data/lib/relay.rb +24 -0
  7. data/lib/resource.rb +113 -0
  8. data/lib/ssl_patch.rb +15 -0
  9. data/lib/switchbox.rb +54 -0
  10. data/lib/time_ext.rb +30 -0
  11. data/lib/version.rb +3 -0
  12. data/sample/config.yml +12 -0
  13. data/vendor/rscm-0.5.1-patched-stripped/README +218 -0
  14. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm.rb +14 -0
  15. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/abstract_log_parser.rb +35 -0
  16. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/base.rb +289 -0
  17. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/command_line.rb +146 -0
  18. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/difftool.rb +44 -0
  19. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/line_editor.rb +46 -0
  20. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/mockit.rb +157 -0
  21. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/parser.rb +39 -0
  22. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/path_converter.rb +60 -0
  23. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/platform.rb +26 -0
  24. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revision.rb +103 -0
  25. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revision_file.rb +85 -0
  26. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revision_poller.rb +93 -0
  27. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/revisions.rb +79 -0
  28. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/clearcase.rb +182 -0
  29. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/cvs.rb +374 -0
  30. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/cvs_log_parser.rb +154 -0
  31. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/darcs.rb +120 -0
  32. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/darcs_log_parser.rb +65 -0
  33. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/monotone.rb +338 -0
  34. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/monotone_log_parser.rb +109 -0
  35. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/mooky.rb +6 -0
  36. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/perforce.rb +216 -0
  37. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/star_team.rb +104 -0
  38. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/subversion.rb +397 -0
  39. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/scm/subversion_log_parser.rb +165 -0
  40. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/tempdir.rb +17 -0
  41. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/time_ext.rb +11 -0
  42. data/vendor/rscm-0.5.1-patched-stripped/lib/rscm/version.rb +13 -0
  43. data/vendor/ruby-feedparser-0.5-stripped/README +14 -0
  44. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser.rb +28 -0
  45. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/feedparser.rb +300 -0
  46. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/filesizes.rb +12 -0
  47. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/html-output.rb +126 -0
  48. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/html2text-parser.rb +409 -0
  49. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/rexml_patch.rb +28 -0
  50. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/sgml-parser.rb +332 -0
  51. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/text-output.rb +83 -0
  52. data/vendor/ruby-feedparser-0.5-stripped/lib/feedparser/textconverters.rb +120 -0
  53. metadata +132 -0
@@ -0,0 +1,165 @@
1
+ require 'rscm/parser'
2
+ require 'rscm/revision'
3
+ require 'rscm/revisions'
4
+ require 'rscm/revision_file'
5
+ require 'time'
6
+
7
+ module RSCM
8
+
9
+ class SubversionLogParser
10
+ def initialize(io, url, exclude_below_and_including=nil, exclude_above_and_including=nil, path=nil)
11
+ @io = io
12
+ @revision_parser = SubversionLogEntryParser.new(url, path)
13
+ @exclude_below_and_including = exclude_below_and_including
14
+ @exclude_above_and_including = exclude_above_and_including
15
+ end
16
+
17
+ def parse_revisions(&line_proc)
18
+ # skip over the first ------
19
+ @revision_parser.parse(@io, true, &line_proc)
20
+ revisions = Revisions.new
21
+ while(!@io.eof?)
22
+ revision = @revision_parser.parse(@io, &line_proc)
23
+ unless(revision.nil?)
24
+ # Filter out the lower bound to avoid inclusiveness of the lower bound (see contract)
25
+ # We're doing this instead of increasing the from_identifer with 1, since that causes an error.
26
+ too_low = false
27
+ too_high = false
28
+ next if revision.time.nil?
29
+ if(@exclude_below_and_including.is_a? Time)
30
+ too_low = revision.time <= @exclude_below_and_including
31
+ elsif(@exclude_below_and_including.is_a? Numeric)
32
+ too_low = revision.identifier <= @exclude_below_and_including
33
+ end
34
+
35
+ if(@exclude_above_and_including.is_a? Time)
36
+ too_high = revision.time >= @exclude_above_and_including
37
+ elsif(@exclude_above_and_including.is_a? Numeric)
38
+ too_high = revision.identifier >= @exclude_above_and_including
39
+ end
40
+ revisions.add(revision) unless too_low || too_high
41
+ end
42
+ end
43
+ revisions
44
+ end
45
+ end
46
+
47
+ class SubversionLogEntryParser < Parser
48
+
49
+ def initialize(url, path=nil)
50
+ super(/^------------------------------------------------------------------------/)
51
+ @url = url
52
+ @path = path
53
+ end
54
+
55
+ def parse(io, skip_line_parsing=false, &line_proc)
56
+ # We have to trim off the last newline - it's not meant to be part of the message
57
+ revision = super
58
+ revision.message = revision.message[0..-2] if revision
59
+ revision
60
+ end
61
+
62
+ def relative_path(url, path_from_root)
63
+ path_from_root = path_from_root.chomp
64
+ url_tokens = url.split('/')
65
+ path_from_root_tokens = path_from_root.split('/')
66
+
67
+ max_similar = path_from_root_tokens.length
68
+ while(max_similar > 0)
69
+ url = url_tokens[-max_similar..-1]
70
+ path = path_from_root_tokens[0..max_similar-1]
71
+ if(url == path)
72
+ break
73
+ end
74
+ max_similar -= 1
75
+ end
76
+
77
+ if(max_similar == 0)
78
+ if(@path.nil? || @path == "")
79
+ path_from_root
80
+ else
81
+ nil
82
+ end
83
+ else
84
+ path_from_root_tokens[max_similar..-1].join("/")
85
+ end
86
+ end
87
+
88
+ protected
89
+
90
+ def parse_line(line)
91
+ if(@revision.nil?)
92
+ parse_header(line)
93
+ elsif(line.strip == "")
94
+ @parse_state = :parse_message
95
+ elsif(line =~ /Changed paths/)
96
+ @parse_state = :parse_files
97
+ elsif(@parse_state == :parse_files)
98
+ file = parse_file(line)
99
+ if(file && file.path)
100
+ previously_added_file = @revision[-1]
101
+ if(previously_added_file)
102
+ # remove previous revision_file if it's a dir
103
+ previous_tokens = previously_added_file.path.split("/")
104
+ current_tokens = file.path.split("/")
105
+ current_tokens.pop
106
+ if(previous_tokens == current_tokens)
107
+ @revision.pop
108
+ end
109
+ end
110
+ @revision.add file
111
+ end
112
+ elsif(@parse_state == :parse_message)
113
+ @revision.message << line.chomp << "\n"
114
+ end
115
+ end
116
+
117
+ def next_result
118
+ result = @revision
119
+ @revision = nil
120
+ result
121
+ end
122
+
123
+ private
124
+
125
+ STATES = {"M" => RevisionFile::MODIFIED, "A" => RevisionFile::ADDED, "D" => RevisionFile::DELETED} unless defined? STATES
126
+
127
+ def parse_header(line)
128
+ @revision = Revision.new
129
+ @revision.message = ""
130
+ revision, developer, time, the_rest = line.split("|")
131
+ @revision.identifier = revision.strip[1..-1].to_i unless revision.nil?
132
+ developer.strip!
133
+ @revision.developer = developer unless developer.nil? || developer == "(no author)"
134
+ time.strip!
135
+ @revision.time = Time.parse(time).utc unless time.nil? || time == "(no date)"
136
+ end
137
+
138
+ def parse_file(line)
139
+ file = RevisionFile.new
140
+ path_from_root = nil
141
+ if(line =~ /^ [M|A|D|R] ([^\s]+) \(from (.*)\)/)
142
+ path_from_root = $1
143
+ file.status = RevisionFile::MOVED
144
+ elsif(line =~ /^ ([M|A|D|R]) (.+)$/)
145
+ status = $1
146
+ path_from_root = $2
147
+ file.status = STATES[status]
148
+ else
149
+ raise "could not parse file line: '#{line}'"
150
+ end
151
+
152
+ path_from_root.gsub!(/\\/, "/")
153
+ path_from_root = path_from_root[1..-1]
154
+ rp = relative_path(@url, path_from_root)
155
+ return if rp.nil?
156
+
157
+ file.path = rp
158
+ file.native_revision_identifier = @revision.identifier
159
+ # http://jira.codehaus.org/browse/DC-204
160
+ file.previous_native_revision_identifier = file.native_revision_identifier.to_i - 1;
161
+ file
162
+ end
163
+ end
164
+
165
+ end
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+
3
+ module RSCM
4
+
5
+ def method_name
6
+ /\`([^\']+)\'/.match(caller.first)[1]
7
+ end
8
+
9
+ def new_temp_dir(suffix="", basedir=File.dirname(__FILE__) + "/../../target")
10
+ identifier = identifier.to_s
11
+ identifier.gsub!(/\(|:|\)/, '_')
12
+ dir = "#{basedir}/temp_#{identifier}_#{Time.new.to_i}#{suffix}"
13
+ FileUtils.mkdir_p(dir)
14
+ dir
15
+ end
16
+ module_function :new_temp_dir
17
+ end
@@ -0,0 +1,11 @@
1
+ class Time
2
+ class << self
3
+ def epoch
4
+ Time.utc(1972)
5
+ end
6
+
7
+ def infinity
8
+ Time.utc(2036)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module RSCM
2
+ module VERSION
3
+ MAJOR = 0
4
+ MINOR = 5
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+
9
+ NAME = "RSCM"
10
+ FULLNAME = "Ruby Source Control Management"
11
+ URL = "http://rscm.rubyforge.org/"
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ Ruby-Feedparser
2
+ -----------------
3
+ by Lucas Nussbaum <lucas@lucas-nussbaum.net>
4
+
5
+ Currently, all the information is provided on
6
+
7
+ http://home.gna.org/ruby-feedparser/
8
+
9
+ If you need to ask questions, feel free to ask them on the
10
+ ruby-feedparser-devel@gna.org mailing list.
11
+
12
+ Ruby-Feedparser is released under the Ruby license (see the LICENSE file),
13
+ which is compatible with the GNU GPL (see the COPYING file) via an explicit
14
+ dual-licensing clause.
@@ -0,0 +1,28 @@
1
+ # =Ruby-feedparser - ATOM/RSS feed parser for Ruby
2
+ # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
3
+ # Website::http://home.gna.org/ruby-feedparser/
4
+ #
5
+ # ==Introduction
6
+ #
7
+ # Ruby-Feedparser is an RSS and Atom parser for Ruby.
8
+ # Ruby-feedparser is :
9
+ # * based on REXML
10
+ # * built for robustness : most feeds are not valid, a parser can't ignore that
11
+ # * fully unit-tested
12
+ # * easy to use (it can output text or HTML easily)
13
+ #
14
+ # ==Example
15
+ # require 'net/http'
16
+ # require 'feedparser'
17
+ # require 'uri'
18
+ # s = Net::HTTP::get URI::parse('http://rss.slashdot.org/Slashdot/slashdot')
19
+ # f = FeedParser::Feed::new(s)
20
+ # f.title
21
+ # => "Slashdot"
22
+ # f.items.each { |i| puts i.title }
23
+ # [...]
24
+ # require 'feedparser/html-output'
25
+ # f.items.each { |i| puts i.to_html }
26
+ #
27
+
28
+ require 'feedparser/feedparser'
@@ -0,0 +1,300 @@
1
+ require 'rexml/document'
2
+ require 'time'
3
+ require 'feedparser/textconverters'
4
+ require 'feedparser/rexml_patch'
5
+ require 'feedparser/text-output'
6
+ require 'base64'
7
+
8
+ module FeedParser
9
+
10
+ VERSION = "0.5"
11
+
12
+ class UnknownFeedTypeException < RuntimeError
13
+ end
14
+
15
+ # an RSS/Atom feed
16
+ class Feed
17
+ attr_reader :type, :title, :link, :description, :creator, :encoding, :items
18
+
19
+ # REXML::Element for this feed.
20
+ attr_reader :xml
21
+
22
+ # parse str to build a Feed
23
+ def initialize(str = nil)
24
+ parse(str) if str
25
+ end
26
+
27
+ # Determines all the fields using a string containing an
28
+ # XML document
29
+ def parse(str)
30
+ # Dirty hack: some feeds contain the & char. It must be changed to &amp;
31
+ str.gsub!(/&(\s+)/, '&amp;\1')
32
+ doc = REXML::Document.new(str)
33
+ @xml = doc.root
34
+ # get feed info
35
+ @encoding = doc.encoding
36
+ @title,@link,@description,@creator = nil
37
+ @items = []
38
+ if doc.root.elements['channel'] || doc.root.elements['rss:channel']
39
+ @type = "rss"
40
+ # We have a RSS feed!
41
+ # Title
42
+ if (e = doc.root.elements['channel/title'] ||
43
+ doc.root.elements['rss:channel/rss:title']) && e.text
44
+ @title = e.text.unescape_html.toUTF8(@encoding).rmWhiteSpace!
45
+ end
46
+ # Link
47
+ if (e = doc.root.elements['channel/link'] ||
48
+ doc.root.elements['rss:channel/rss:link']) && e.text
49
+ @link = e.text.rmWhiteSpace!
50
+ end
51
+ # Description
52
+ if (e = doc.root.elements['channel/description'] ||
53
+ doc.root.elements['rss:channel/rss:description']) && e.text
54
+ @description = e.text.toUTF8(@encoding).rmWhiteSpace!
55
+ end
56
+ # Creator
57
+ if ((e = doc.root.elements['channel/dc:creator']) && e.text) ||
58
+ ((e = doc.root.elements['channel/author'] ||
59
+ doc.root.elements['rss:channel/rss:author']) && e.text)
60
+ @creator = e.text.unescape_html.toUTF8(@encoding).rmWhiteSpace!
61
+ end
62
+ # Items
63
+ if doc.root.elements['channel/item']
64
+ query = 'channel/item'
65
+ elsif doc.root.elements['item']
66
+ query = 'item'
67
+ elsif doc.root.elements['rss:channel/rss:item']
68
+ query = 'rss:channel/rss:item'
69
+ else
70
+ query = 'rss:item'
71
+ end
72
+ doc.root.each_element(query) { |e| @items << RSSItem::new(e, self) }
73
+
74
+ elsif doc.root.elements['/feed']
75
+ # We have an ATOM feed!
76
+ @type = "atom"
77
+ # Title
78
+ if (e = doc.root.elements['/feed/title']) && e.text
79
+ @title = e.text.unescape_html.toUTF8(@encoding).rmWhiteSpace!
80
+ end
81
+ # Link
82
+ doc.root.each_element('/feed/link') do |e|
83
+ if e.attribute('type') and (
84
+ e.attribute('type').value == 'text/html' or
85
+ e.attribute('type').value == 'application/xhtml' or
86
+ e.attribute('type').value == 'application/xhtml+xml')
87
+ if (h = e.attribute('href')) && h
88
+ @link = h.value.rmWhiteSpace!
89
+ end
90
+ end
91
+ end
92
+ # Description
93
+ if e = doc.root.elements['/feed/info']
94
+ e = e.elements['div'] || e
95
+ @description = e.to_s.toUTF8(@encoding).rmWhiteSpace!
96
+ end
97
+ # Items
98
+ doc.root.each_element('/feed/entry') do |e|
99
+ @items << AtomItem::new(e, self)
100
+ end
101
+ else
102
+ raise UnknownFeedTypeException::new
103
+ end
104
+ end
105
+
106
+ def to_s(localtime = true)
107
+ s = ''
108
+ s += "Type: #{@type}\n"
109
+ s += "Encoding: #{@encoding}\n"
110
+ s += "Title: #{@title}\n"
111
+ s += "Link: #{@link}\n"
112
+ s += "Description: #{@description}\n"
113
+ s += "Creator: #{@creator}\n"
114
+ s += "\n"
115
+ @items.each { |i| s += i.to_s(localtime) }
116
+ s
117
+ end
118
+ end
119
+
120
+ # an Item from a feed
121
+ class FeedItem
122
+ attr_accessor :title, :link, :content, :date, :creator, :subject,
123
+ :category, :cacheditem
124
+
125
+ # The item's enclosures childs. An array of (url, length, type) triplets.
126
+ attr_accessor :enclosures
127
+
128
+ attr_reader :feed
129
+
130
+ # REXML::Element for this item
131
+ attr_reader :xml
132
+
133
+ def initialize(item = nil, feed = nil)
134
+ @xml = item
135
+ @feed = feed
136
+ @title, @link, @content, @date, @creator, @subject, @category = nil
137
+ @enclosures = []
138
+ parse(item) if item
139
+ end
140
+
141
+ def parse(item)
142
+ raise "parse() should be implemented by subclasses!"
143
+ end
144
+
145
+ def to_s(localtime = true)
146
+ s = "--------------------------------\n" +
147
+ "Title: #{@title}\nLink: #{@link}\n"
148
+ if localtime or @date.nil?
149
+ s += "Date: #{@date.to_s}\n"
150
+ else
151
+ s += "Date: #{@date.getutc.to_s}\n"
152
+ end
153
+ s += "Creator: #{@creator}\n" +
154
+ "Subject: #{@subject}\nCategory: #{@category}\nContent:\n#{content}\n"
155
+ if defined?(@enclosures) and @enclosures.length > 0
156
+ s2 = "Enclosures:\n"
157
+ @enclosures.each do |e|
158
+ s2 += e.join(' ') + "\n"
159
+ end
160
+ s += s2
161
+ end
162
+ return s
163
+ end
164
+ end
165
+
166
+ class RSSItem < FeedItem
167
+
168
+
169
+ def parse(item)
170
+ # Title. If no title, use the pubDate as fallback.
171
+ if ((e = item.elements['title'] || item.elements['rss:title']) &&
172
+ e.text) ||
173
+ ((e = item.elements['pubDate'] || item.elements['rss:pubDate']) &&
174
+ e.text)
175
+ @title = e.text.unescape_html.toUTF8(@feed.encoding).html2text.rmWhiteSpace!
176
+ end
177
+ # Link
178
+ if ((e = item.elements['link'] || item.elements['rss:link']) && e.text)||
179
+ (e = item.elements['guid'] || item.elements['rss:guid'] and
180
+ not (e.attribute('isPermaLink') and
181
+ e.attribute('isPermaLink').value == 'false'))
182
+ @link = e.text.rmWhiteSpace!
183
+ end
184
+ # Content
185
+ if (e = item.elements['content:encoded']) ||
186
+ (e = item.elements['description'] || item.elements['rss:description'])
187
+ @content = FeedParser::getcontent(e, @feed)
188
+ end
189
+ # Date
190
+ if e = item.elements['dc:date'] || item.elements['pubDate'] ||
191
+ item.elements['rss:pubDate']
192
+ begin
193
+ @date = Time::xmlschema(e.text)
194
+ rescue
195
+ begin
196
+ @date = Time::rfc2822(e.text)
197
+ rescue
198
+ begin
199
+ @date = Time::parse(e.text)
200
+ rescue
201
+ @date = nil
202
+ end
203
+ end
204
+ end
205
+ end
206
+ # Creator
207
+ @creator = @feed.creator
208
+ if (e = item.elements['dc:creator'] || item.elements['author'] ||
209
+ item.elements['rss:author']) && e.text
210
+ @creator = e.text.unescape_html.toUTF8(@feed.encoding).rmWhiteSpace!
211
+ end
212
+ # Subject
213
+ if (e = item.elements['dc:subject']) && e.text
214
+ @subject = e.text.unescape_html.toUTF8(@feed.encoding).rmWhiteSpace!
215
+ end
216
+ # Category
217
+ if (e = item.elements['dc:category'] || item.elements['category'] ||
218
+ item.elements['rss:category']) && e.text
219
+ @category = e.text.unescape_html.toUTF8(@feed.encoding).rmWhiteSpace!
220
+ end
221
+ # Enclosures
222
+ item.each_element('enclosure') do |e|
223
+ url = e.attribute('url').value if e.attribute('url')
224
+ length = e.attribute('length').value if e.attribute('length')
225
+ type = e.attribute('type').value if e.attribute('type')
226
+ @enclosures << [ url, length, type ] if url
227
+ end
228
+ end
229
+ end
230
+
231
+ class AtomItem < FeedItem
232
+ def parse(item)
233
+ # Title
234
+ if (e = item.elements['title']) && e.text
235
+ @title = e.text.unescape_html.toUTF8(@feed.encoding).html2text.rmWhiteSpace!
236
+ end
237
+ # Link
238
+ item.each_element('link') do |e|
239
+ if (h = e.attribute('href')) && h.value
240
+ @link = h.value
241
+ end
242
+ end
243
+ # Content
244
+ if e = item.elements['content'] || item.elements['summary']
245
+ if (e.attribute('mode') and e.attribute('mode').value == 'escaped') &&
246
+ e.text
247
+ @content = e.text.toUTF8(@feed.encoding).rmWhiteSpace!
248
+ else
249
+ @content = FeedParser::getcontent(e, @feed)
250
+ end
251
+ end
252
+ # Date
253
+ if (e = item.elements['issued'] || e = item.elements['created'] || e = item.elements['updated'] || e = item.elements['published']) && e.text
254
+ begin
255
+ @date = Time::xmlschema(e.text)
256
+ rescue
257
+ begin
258
+ @date = Time::rfc2822(e.text)
259
+ rescue
260
+ begin
261
+ @date = Time::parse(e.text)
262
+ rescue
263
+ @date = nil
264
+ end
265
+ end
266
+ end
267
+ end
268
+ # Creator
269
+ @creator = @feed.creator
270
+ if (e = item.elements['author/name']) && e.text
271
+ @creator = e.text.unescape_html.toUTF8(@feed.encoding).rmWhiteSpace!
272
+ end
273
+ end
274
+ end
275
+
276
+ def FeedParser::getcontent(e, feed = nil)
277
+ encoding = feed ? feed.encoding : 'utf-8'
278
+ children = e.children.reject do |i|
279
+ i.class == REXML::Text and i.to_s.chomp == ''
280
+ end
281
+ if children.length > 1
282
+ s = ''
283
+ children.each do |c|
284
+ s += c.to_s if c.class != REXML::Comment
285
+ end
286
+ return s.toUTF8(encoding).rmWhiteSpace!.text2html(feed)
287
+ elsif children.length == 1
288
+ c = children[0]
289
+ if c.class == REXML::Text
290
+ return e.text.toUTF8(encoding).rmWhiteSpace!.text2html(feed)
291
+ else
292
+ if c.class == REXML::CData
293
+ return c.to_s.toUTF8(encoding).rmWhiteSpace!.text2html(feed)
294
+ elsif c.text
295
+ return c.text.toUTF8(encoding).text2html(feed)
296
+ end
297
+ end
298
+ end
299
+ end
300
+ end