1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
"""XML-RPC methods of Gstudio Pingback"""
from urllib2 import urlopen
from urllib2 import URLError
from urllib2 import HTTPError
from urlparse import urlsplit
from django.contrib import comments
from django.utils.html import strip_tags
from django.contrib.sites.models import Site
from django.core.urlresolvers import resolve
from django.core.urlresolvers import Resolver404
from django.utils.translation import ugettext as _
from django.contrib.contenttypes.models import ContentType
from gstudio.models import Nodetype
from gstudio.settings import PINGBACK_CONTENT_LENGTH
from BeautifulSoup import BeautifulSoup
from django_xmlrpc.decorators import xmlrpc_func
UNDEFINED_ERROR = 0
SOURCE_DOES_NOT_EXIST = 16
SOURCE_DOES_NOT_LINK = 17
TARGET_DOES_NOT_EXIST = 32
TARGET_IS_NOT_PINGABLE = 33
PINGBACK_ALREADY_REGISTERED = 48
def generate_pingback_content(soup, target, max_length, trunc_char='...'):
"""Generate a description text for the pingback"""
link = soup.find('a', href=target)
content = strip_tags(unicode(link.findParent()))
index = content.index(link.string)
if len(content) > max_length:
middle = max_length / 2
start = index - middle
end = index + middle
if start <= 0:
end -= start
extract = content[0:end]
else:
extract = '%s%s' % (trunc_char, content[start:end])
if end < len(content):
extract += trunc_char
return extract
return content
@xmlrpc_func(returns='string', args=['string', 'string'])
def pingback_ping(source, target):
"""pingback.ping(sourceURI, targetURI) => 'Pingback message'
Notifies the server that a link has been added to sourceURI,
pointing to targetURI.
See: http://hixie.ch/specs/pingback/pingback-1.0"""
try:
if source == target:
return UNDEFINED_ERROR
site = Site.objects.get_current()
try:
document = ''.join(urlopen(source).readlines())
except (HTTPError, URLError):
return SOURCE_DOES_NOT_EXIST
if not target in document:
return SOURCE_DOES_NOT_LINK
scheme, netloc, path, query, fragment = urlsplit(target)
if netloc != site.domain:
return TARGET_DOES_NOT_EXIST
try:
view, args, kwargs = resolve(path)
except Resolver404:
return TARGET_DOES_NOT_EXIST
try:
nodetype = Nodetype.published.get(
slug=kwargs['slug'],
creation_date__year=kwargs['year'],
creation_date__month=kwargs['month'],
creation_date__day=kwargs['day'])
if not nodetype.pingback_enabled:
return TARGET_IS_NOT_PINGABLE
except (KeyError, Nodetype.DoesNotExist):
return TARGET_IS_NOT_PINGABLE
soup = BeautifulSoup(document)
title = soup.find('title')
title = title and strip_tags(title) or _('No title')
description = generate_pingback_content(soup, target,
PINGBACK_CONTENT_LENGTH)
comment, created = comments.get_model().objects.get_or_create(
content_type=ContentType.objects.get_for_model(Nodetype),
object_pk=nodetype.pk, user_url=source, site=site,
defaults={'comment': description, 'user_name': title})
if created:
user = nodetype.authors.all()[0]
comment.flags.create(user=user, flag='pingback')
return 'Pingback from %s to %s registered.' % (source, target)
return PINGBACK_ALREADY_REGISTERED
except:
return UNDEFINED_ERROR
@xmlrpc_func(returns='string[]', args=['string'])
def pingback_extensions_get_pingbacks(target):
"""pingback.extensions.getPingbacks(url) => '[url, url, ...]'
Returns an array of URLs that link to the specified url.
See: http://www.aquarionics.com/misc/archives/blogite/0198.html"""
site = Site.objects.get_current()
scheme, netloc, path, query, fragment = urlsplit(target)
if netloc != site.domain:
return TARGET_DOES_NOT_EXIST
try:
view, args, kwargs = resolve(path)
except Resolver404:
return TARGET_DOES_NOT_EXIST
try:
nodetype = Nodetype.published.get(
slug=kwargs['slug'],
creation_date__year=kwargs['year'],
creation_date__month=kwargs['month'],
creation_date__day=kwargs['day'])
except (KeyError, Nodetype.DoesNotExist):
return TARGET_IS_NOT_PINGABLE
return [pingback.user_url for pingback in nodetype.pingbacks]
|