require 'action_view' module Relevance module Tarantula class Link include Relevance::Tarantula class << self include ActionView::Helpers::UrlHelper # method_javascript_function needs this method def protect_against_forgery? false end #fast fix for rails3 def method_javascript_function(method, url = '', href = nil) action = (href && url.size > 0) ? "'#{url}'" : 'this.href' submit_function = "var f = document.createElement('form'); f.style.display = 'none'; " + "this.parentNode.appendChild(f); f.method = 'POST'; f.action = #{action};" unless method == 'post' submit_function << "var m = document.createElement('input'); m.setAttribute('type', 'hidden'); " submit_function << "m.setAttribute('name', '_method'); m.setAttribute('value', '#{method}'); f.appendChild(m);" end if protect_against_forgery? submit_function << "var s = document.createElement('input'); s.setAttribute('type', 'hidden'); " submit_function << "s.setAttribute('name', '#{request_forgery_protection_token}'); s.setAttribute('value', '#{escape_javascript form_authenticity_token}'); f.appendChild(s);" end submit_function << "f.submit();" end end METHOD_REGEXPS = {} %w(put delete post patch).each do |m| # remove submit from the end so we'll match with or without forgery protection s = method_javascript_function(m).gsub( /f.submit();/, "" ) # don't just match this.href in case a different url was passed originally s = Regexp.escape(s).gsub( /this.href/, ".*" ) METHOD_REGEXPS[m] = /#{s}/ end attr_accessor :href, :crawler, :referrer def initialize(link, crawler, referrer) @crawler, @referrer = crawler, referrer if String === link || link.nil? @href = transform_url(link) @method = 'get' else # should be a tag @href = link['href'] ? transform_url(link['href']) : nil @tag = link end end def crawl response = crawler.follow(meth, href) log "Response #{response.code} for #{self}" crawler.handle_link_results(self, make_result(response)) end def make_result(response) crawler.make_result(:method => meth, :url => href, :response => response, :referrer => referrer) end def meth @meth ||= begin (@tag && %w(put delete post patch).detect do |m| # post should be last since it's least specific @tag['onclick'] =~ METHOD_REGEXPS[m] || @tag['data-method'] == m end) || 'get' end end def url href end def transform_url(link) crawler.transform_url(link) end def ==(obj) obj.respond_to?(:href) && obj.respond_to?(:method) && self.href.to_s == obj.href.to_s && self.meth.to_s == obj.meth.to_s end alias :eql? :== def hash to_s.hash end def to_s "" end end end end