require 'rexml/document'
require 'xmlrpc/client'
class Ping < ActiveRecord::Base
belongs_to :article
class Pinger
attr_accessor :article
attr_accessor :blog
def send_pingback_or_trackback
@response = Net::HTTP.get_response(URI.parse(ping.url))
send_pingback or send_trackback
rescue Timeout::Error
Rails.logger.info 'Sending pingback or trackback timed out'
return
rescue => err
Rails.logger.info "Sending pingback or trackback failed with error: #{err}"
end
def pingback_url
if response['X-Pingback']
response['X-Pingback']
elsif response.body =~ //
Regexp.last_match[1]
end
end
attr_reader :origin_url
attr_reader :response
attr_reader :ping
def send_xml_rpc(*args)
ping.send(:send_xml_rpc, *args)
end
def trackback_url
rdfs = response.body.scan(//m)
rdfs.each do |rdf|
xml = REXML::Document.new(rdf)
xml.elements.each('//rdf:Description') do |desc|
if rdfs.size == 1 || desc.attributes['dc:identifier'] == ping.url
return desc.attributes['trackback:ping']
end
end
end
# Didn't find a trackback url, so fall back to the url itself.
@ping.url
end
def send_pingback
if pingback_url
send_xml_rpc(pingback_url, 'pingback.ping', origin_url, ping.url)
true
else
false
end
end
def send_trackback
do_send_trackback(trackback_url, origin_url)
end
def do_send_trackback(trackback_url, origin_url)
trackback_uri = URI.parse(trackback_url)
post = "title=#{CGI.escape(article.title)}"
post << "&excerpt=#{CGI.escape(article.html(:body).strip_html[0..254])}"
post << "&url=#{origin_url}"
post << "&blog_name=#{CGI.escape(blog.blog_name)}"
path = trackback_uri.path
path += "?#{trackback_uri.query}" if trackback_uri.query
Net::HTTP.start(trackback_uri.host, trackback_uri.port) do |http|
http.post(path, post, 'Content-type' => 'application/x-www-form-urlencoded; charset=utf-8')
end
end
private
def initialize(origin_url, ping)
@origin_url = origin_url
@ping = ping
# Add this call to text filter cause of a strange thing around text_filter. Need to clean text_filter usage !
ping.article.default_text_filter
ping.article.text_filter
# Make sure these are fetched now for thread safety purposes.
self.article = ping.article
self.blog = article.blog
end
end
def send_pingback_or_trackback(origin_url)
t = Thread.start(Pinger.new(origin_url, self), &:send_pingback_or_trackback)
t
end
def send_weblogupdatesping(server_url, origin_url)
t = Thread.start(article.blog.blog_name) do |blog_name|
send_xml_rpc(url, 'weblogUpdates.ping', blog_name, server_url, origin_url)
end
t
end
protected
def send_xml_rpc(xml_rpc_url, name, *args)
server = XMLRPC::Client.new2(URI.parse(xml_rpc_url).to_s)
server.call(name, *args)
rescue => e
logger.error(e)
end
end