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
18 """Object defining the ressources of the website"""
19
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
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
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
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
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
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
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
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
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
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