rfeedfinderを修正

Fastladderのオープンソース版を試していると、feedの登録&取得に失敗するケースがあります(例: http://www.ruby-lang.org/ja/ )。根本をたどってみると、feedを探索するライブラリ、rfeedfinder(ver.0.9.13)に問題があるようです。具体的には、下記のisAValidURL関数です。

  def self.isAValidURL?(url_to_check)
    return false if url_to_check == nil

    # The protocols that we allow are the following
    protocol_whitelist = ["http", "https"]
    # I guess we could have included some more, but that doesn't really
    # make sense anyway as these are the ones that should be used.
    # We'll see if the need arises and then add more later if needed.

    re = Regexp.new("(#{protocol_whitelist.join('|')}):" + \
      "\/\/([[:alpha:][:digit:].]{2,})([.]{1})([[:alpha:]]{2,4})(\/)")

    # For the sake of the regular expression check we add a back slash
    # at the end of the URL
    url_to_check += "/"
    return true unless (re =~ url_to_check) == nil
    false
  end

正規表現https?://hogehoge.example.com/ などの正規なURLであることを判別しているようです。しかし、この正規表現ではハイフンやポート番号に対応していません。というわけで、URIモジュールを使って修正しました。makeFullURI関数も難ありだったので、適宜直しています。

Index: lib/rfeedfinder.rb
===================================================================
--- lib/rfeedfinder.rb  (revision 1)
+++ lib/rfeedfinder.rb  (working copy)
@@ -314,11 +314,23 @@

   protected
   def self.makeFullURI(uri)
-    uri = uri.strip.sub(/^feed(.*)/, 'http\1').downcase
-    if /^http|https/.match(uri)
+    begin
+      uri_parsed = URI.parse(uri)
+    rescue URI::Error
       return uri
+    end
+
+    case uri_parsed.scheme
+    when "http", "https"
+      return uri
+    when "feed"
+      uri = uri.strip.sub(/^feed(.*)/, 'http\1').downcase
+      return uri
+    when nil
+      # when uri does not start with 'protocol-scheme://', add 'http://'
+      return "http://" << uri
     else
-      return "http://" << uri
+      return uri
     end
   end

@@ -481,14 +493,16 @@
     # make sense anyway as these are the ones that should be used.
     # We'll see if the need arises and then add more later if needed.

-    re = Regexp.new("(#{protocol_whitelist.join('|')}):" + \
-      "\/\/([[:alpha:][:digit:].]{2,})([.]{1})([[:alpha:]]{2,4})(\/)")
-
-    # For the sake of the regular expression check we add a back slash
-    # at the end of the URL
-    url_to_check += "/"
-    return true unless (re =~ url_to_check) == nil
-    false
+    begin
+      uri = URI.parse(url_to_check)
+      if protocol_whitelist.index(uri.scheme)
+        return true
+      else
+        return false
+      end
+    rescue URI::Error
+      return false
+    end
   end

makeFullURIのdowncaseについてはこのままだとまずいらしい(たとえば、URLがcase-sensitiveなとき)ですが、rfeedfinder作者の意図が分からないので判断は保留で。