Package zinnia :: Module ping
[hide private]

Source Code for Module zinnia.ping

  1  """Pings utilities for Zinnia""" 
  2  import socket 
  3  import xmlrpclib 
  4  import threading 
  5  from urllib2 import urlopen 
  6  from urlparse import urlsplit 
  7  from logging import getLogger 
  8   
  9  from BeautifulSoup import BeautifulSoup 
 10   
 11  from django.contrib.sites.models import Site 
 12  from django.core.urlresolvers import reverse 
 13   
 14  from zinnia.settings import PROTOCOL 
 15   
 16   
17 -class URLRessources(object):
18 """Object defining the ressources of the website""" 19
20 - def __init__(self):
21 self.current_site = Site.objects.get_current() 22 self.site_url = '%s://%s' % (PROTOCOL, self.current_site.domain) 23 self.blog_url = '%s%s' % (self.site_url, 24 reverse('zinnia_entry_archive_index')) 25 self.blog_feed = '%s%s' % (self.site_url, 26 reverse('zinnia_entry_latest_feed'))
27 28
29 -class DirectoryPinger(threading.Thread):
30 """Threaded Directory Pinger""" 31
32 - def __init__(self, server_name, entries, timeout=10, start_now=True):
33 self.results = [] 34 self.timeout = timeout 35 self.entries = entries 36 self.server_name = server_name 37 self.server = xmlrpclib.ServerProxy(self.server_name) 38 self.ressources = URLRessources() 39 40 threading.Thread.__init__(self) 41 if start_now: 42 self.start()
43
44 - def run(self):
45 """Ping entries to a Directory in a Thread""" 46 logger = getLogger('zinnia.ping.directory') 47 socket.setdefaulttimeout(self.timeout) 48 for entry in self.entries: 49 reply = self.ping_entry(entry) 50 self.results.append(reply) 51 logger.info('%s : %s' % (self.server_name, reply['message'])) 52 socket.setdefaulttimeout(None)
53
54 - def ping_entry(self, entry):
55 """Ping an entry to a Directory""" 56 entry_url = '%s%s' % (self.ressources.site_url, 57 entry.get_absolute_url()) 58 categories = '|'.join([c.title for c in entry.categories.all()]) 59 60 try: 61 reply = self.server.weblogUpdates.extendedPing( 62 self.ressources.current_site.name, 63 self.ressources.blog_url, entry_url, 64 self.ressources.blog_feed, categories) 65 except Exception: 66 try: 67 reply = self.server.weblogUpdates.ping( 68 self.ressources.current_site.name, 69 self.ressources.blog_url, entry_url, 70 categories) 71 except Exception: 72 reply = {'message': '%s is an invalid directory.' % \ 73 self.server_name, 74 'flerror': True} 75 return reply
76 77
78 -class ExternalUrlsPinger(threading.Thread):
79 """Threaded ExternalUrls Pinger""" 80
81 - def __init__(self, entry, timeout=10, start_now=True):
82 self.results = [] 83 self.entry = entry 84 self.timeout = timeout 85 self.ressources = URLRessources() 86 self.entry_url = '%s%s' % (self.ressources.site_url, 87 self.entry.get_absolute_url()) 88 89 threading.Thread.__init__(self) 90 if start_now: 91 self.start()
92
93 - def run(self):
94 """Ping external URLS in a Thread""" 95 logger = getLogger('zinnia.ping.external_urls') 96 socket.setdefaulttimeout(self.timeout) 97 98 external_urls = self.find_external_urls(self.entry) 99 external_urls_pingable = self.find_pingback_urls(external_urls) 100 101 for url, server_name in external_urls_pingable.items(): 102 reply = self.pingback_url(server_name, url) 103 self.results.append(reply) 104 logger.info('%s : %s' % (url, reply)) 105 106 socket.setdefaulttimeout(None)
107
108 - def is_external_url(self, url, site_url):
109 """Check of the url in an external url""" 110 url_splitted = urlsplit(url) 111 if not url_splitted.netloc: 112 return False 113 return url_splitted.netloc != urlsplit(site_url).netloc
114
115 - def find_external_urls(self, entry):
116 """Find external urls in an entry""" 117 soup = BeautifulSoup(entry.html_content) 118 external_urls = [a['href'] for a in soup.findAll('a') 119 if self.is_external_url( 120 a['href'], self.ressources.site_url)] 121 return external_urls
122
123 - def find_pingback_href(self, content):
124 """Try to find Link markup to pingback url""" 125 soup = BeautifulSoup(content) 126 for link in soup.findAll('link'): 127 dict_attr = dict(link.attrs) 128 if 'rel' in dict_attr and 'href' in dict_attr: 129 if dict_attr['rel'].lower() == 'pingback': 130 return dict_attr.get('href')
131
132 - def find_pingback_urls(self, urls):
133 """Find the pingback urls of each urls""" 134 pingback_urls = {} 135 136 for url in urls: 137 try: 138 page = urlopen(url) 139 server_url = page.info().get('X-Pingback') or \ 140 self.find_pingback_href(page.read()) 141 if server_url: 142 server_url_splitted = urlsplit(server_url) 143 if not server_url_splitted.netloc: 144 url_splitted = urlsplit(url) 145 server_url = '%s://%s%s' % (url_splitted.scheme, 146 url_splitted.netloc, 147 server_url) 148 pingback_urls[url] = server_url 149 except IOError: 150 pass 151 return pingback_urls
152
153 - def pingback_url(self, server_name, target_url):
154 """Do a pingback call for the target url""" 155 try: 156 server = xmlrpclib.ServerProxy(server_name) 157 reply = server.pingback.ping(self.entry_url, target_url) 158 except xmlrpclib.Error: 159 reply = '%s cannot be pinged.' % target_url 160 return reply
161