| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
from lahak.vertical.core.protocols import supported_protocols, get_protocol_display |
|---|
| 22 |
from lahak.vertical.uploads.models import Image, Audio |
|---|
| 23 |
from lahak.vertical.core.templatetags.lahak_general import resize |
|---|
| 24 |
from django.db.models.base import ObjectDoesNotExist |
|---|
| 25 |
import urllib, re |
|---|
| 26 |
from django.utils.translation import ugettext as _ |
|---|
| 27 |
|
|---|
| 28 |
class ProtocolsPreProcessor(object): |
|---|
| 29 |
"Converts lahak supported protocols in the content to links" |
|---|
| 30 |
|
|---|
| 31 |
def __call__(self, content): |
|---|
| 32 |
|
|---|
| 33 |
autolinks = supported_protocols.get_regexp().findall(content) |
|---|
| 34 |
|
|---|
| 35 |
for match in autolinks: |
|---|
| 36 |
the_model = supported_protocols.get_protocols()[match[1]] |
|---|
| 37 |
try: |
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
lookup = { the_model.LahakMeta.protocol.get('lookup','id'): match[2] } |
|---|
| 41 |
|
|---|
| 42 |
data = the_model.objects.get(**lookup) |
|---|
| 43 |
label = get_protocol_display(data) |
|---|
| 44 |
|
|---|
| 45 |
content = content.replace( match[0], r"`%s <%s>`_" % (label, data.get_absolute_url() ) ) |
|---|
| 46 |
except ObjectDoesNotExist: |
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
|
|---|
| 50 |
|
|---|
| 51 |
new_path = the_model.LahakMeta.protocol.get('new_path', None) |
|---|
| 52 |
if new_path: |
|---|
| 53 |
content = content.replace(match[0], r"`%s <%s%s>`_" % ( match[2], new_path, urllib.quote_plus( match[2].encode('utf-8') )) ) |
|---|
| 54 |
else: |
|---|
| 55 |
|
|---|
| 56 |
|
|---|
| 57 |
content = content.replace(match[0], r"`%s </error_404>`_" % match[2]) |
|---|
| 58 |
|
|---|
| 59 |
return content |
|---|
| 60 |
|
|---|
| 61 |
class UploadedImagePreProcessor(object): |
|---|
| 62 |
"""Converts lahak image directive pointing to an image id to proper reST |
|---|
| 63 |
directives. |
|---|
| 64 |
|
|---|
| 65 |
If width or height is smaller than original image, creates thumbnails |
|---|
| 66 |
on the fly""" |
|---|
| 67 |
|
|---|
| 68 |
regexp = re.compile( '\.\. (%s|image):: (\d+)((\s+:.+:\s+.*?\s*\n)*)' % _('image'), re.MULTILINE ) |
|---|
| 69 |
width_regexp = re.compile(r'([ |\t]*):(%s|width):\s+(\d+)' % _('width')) |
|---|
| 70 |
height_regexp= re.compile(r'([ |\t]*):(%s|height):\s+(\d+)' % _('height')) |
|---|
| 71 |
|
|---|
| 72 |
def _replace_image_url( self, matchobj ): |
|---|
| 73 |
|
|---|
| 74 |
params = matchobj.group(3) |
|---|
| 75 |
url = '.. %s:: %s%s' |
|---|
| 76 |
try: |
|---|
| 77 |
img = Image.objects.get(pk=int(matchobj.group(2))) |
|---|
| 78 |
|
|---|
| 79 |
width_match = self.width_regexp.findall(params) |
|---|
| 80 |
height_match = self.height_regexp.findall(params) |
|---|
| 81 |
|
|---|
| 82 |
|
|---|
| 83 |
if width_match: |
|---|
| 84 |
width = int(width_match[0][2]) |
|---|
| 85 |
image_url = resize(img.get_image_url() ,'width=%d' % width) |
|---|
| 86 |
params = "\n%s:target: %s%s" % (width_match[0][0], img.get_image_url(), params) |
|---|
| 87 |
elif height_match: |
|---|
| 88 |
height = int(height_match[0][2]) |
|---|
| 89 |
image_url = resize(img.get_image_url() ,'height=%d' % height) |
|---|
| 90 |
params = "\n%s:target: %s%s" % (height_match[0][0], img.get_image_url(), params) |
|---|
| 91 |
else: |
|---|
| 92 |
image_url = img.get_image_url() |
|---|
| 93 |
|
|---|
| 94 |
return url % ( matchobj.group(1), image_url , params ) |
|---|
| 95 |
except ObjectDoesNotExist: |
|---|
| 96 |
return url % ( matchobj.group(1), matchobj.group(2) ) |
|---|
| 97 |
|
|---|
| 98 |
def __call__(self, content): |
|---|
| 99 |
content = self.regexp.sub(self._replace_image_url, content) |
|---|
| 100 |
return content |
|---|
| 101 |
|
|---|
| 102 |
|
|---|
| 103 |
class ParameterTranslationPreProcessor(object): |
|---|
| 104 |
"""Replaces translated reST paramaters to original ones |
|---|
| 105 |
(reST doesn't support param translations)""" |
|---|
| 106 |
|
|---|
| 107 |
translations = ( |
|---|
| 108 |
( _('width'), 'width' ), |
|---|
| 109 |
( _('height'), 'height' ), |
|---|
| 110 |
( _('alt'), 'alt' ), |
|---|
| 111 |
) |
|---|
| 112 |
|
|---|
| 113 |
def __call__(self, content): |
|---|
| 114 |
|
|---|
| 115 |
|
|---|
| 116 |
for tr in self.translations: |
|---|
| 117 |
content = content.replace( ':%s:' % tr[0], ':%s:' % tr[1]) |
|---|
| 118 |
return content |
|---|
| 119 |
|
|---|
| 120 |
|
|---|
| 121 |
class AdmonitionsPreProcessor(object): |
|---|
| 122 |
"""Translate block admonitions to general admonition. |
|---|
| 123 |
|
|---|
| 124 |
Since we want the special style name generated by admonitions, but can't |
|---|
| 125 |
support unicode (hence Hebrew in style names, a post precessor is also |
|---|
| 126 |
required""" |
|---|
| 127 |
|
|---|
| 128 |
translations = ( |
|---|
| 129 |
( _('exercise'), 'exercise' ), |
|---|
| 130 |
( _('quote'), 'quote' ), |
|---|
| 131 |
) |
|---|
| 132 |
|
|---|
| 133 |
def __call__(self, content): |
|---|
| 134 |
for tr in self.translations: |
|---|
| 135 |
content = content.replace( '.. %s::' % tr[0], '.. admonition:: %s' % tr[1]) |
|---|
| 136 |
return content |
|---|
| 137 |
|
|---|
| 138 |
class SanitizePreProcessor(object): |
|---|
| 139 |
"""Sanitize unwanted javascript (and other) in links""" |
|---|
| 140 |
|
|---|
| 141 |
regexp_hyperlink = re.compile(r'(\.\.\s*\_.*?:\s*)(.*script:)(.*)', re.MULTILINE) |
|---|
| 142 |
regexp_hyperlink_embedded = re.compile(r'(\`.*?\<)(.*?script:)(.*?\>\`_)', re.MULTILINE) |
|---|
| 143 |
|
|---|
| 144 |
|
|---|
| 145 |
def __call__(self, content): |
|---|
| 146 |
content = self.regexp_hyperlink.sub(r'\1script_not_allowed\3', content) |
|---|
| 147 |
content = self.regexp_hyperlink_embedded.sub(r'\1script_not_allowed\3', content) |
|---|
| 148 |
return content |
|---|
| 149 |
|
|---|
| 150 |
class UploadedAudioPreProcessor(object): |
|---|
| 151 |
|
|---|
| 152 |
|
|---|
| 153 |
|
|---|
| 154 |
|
|---|
| 155 |
def __call__(self, content): |
|---|
| 156 |
|
|---|
| 157 |
def repl_func(match): |
|---|
| 158 |
return "lahakaudio__%s__lahakaudio" % match.group(1) |
|---|
| 159 |
|
|---|
| 160 |
re_str = u"\|%s\|(\d+)\|" % _("audio") |
|---|
| 161 |
|
|---|
| 162 |
content = re.sub(re_str, repl_func,content) |
|---|
| 163 |
|
|---|
| 164 |
return content |
|---|
| 165 |
|
|---|
| 166 |
|
|---|
| 167 |
|
|---|
| 168 |
|
|---|
| 169 |
YOUTUBE_STR = r""" |
|---|
| 170 |
<object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/\1"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/\1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object> |
|---|
| 171 |
|
|---|
| 172 |
""" |
|---|
| 173 |
|
|---|
| 174 |
YOUTUBE_HELP = "youtube.com/watch?v=xxx "+ _("will be") +" xxx" |
|---|
| 175 |
|
|---|
| 176 |
GOOGLE_VIDEO_STR = r""" |
|---|
| 177 |
<embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=\1&hl=en" flashvars=""> </embed> |
|---|
| 178 |
""" |
|---|
| 179 |
|
|---|
| 180 |
GOOGLE_VIDEO_HELP = "video.google.com/videoplay?docid=-xyz " + _("will be") + " -xyz" |
|---|
| 181 |
|
|---|
| 182 |
FLICKR_STR = r""" |
|---|
| 183 |
<iframe align="center" src="http://www.flickr.com/photos/\1/show/" frameborder="0" width="100%" height="500" scrolling="yes"></iframe> |
|---|
| 184 |
""" |
|---|
| 185 |
|
|---|
| 186 |
FLICKR_HELP = "flickr.com/photos/user_name/ "+ _("will be") +" user_name, flickr.com/photos/user_name/tags/airplane/ " + _("will be") +" usrename/tags/airplane " |
|---|
| 187 |
|
|---|
| 188 |
VIDEO_STR = r"""<embed height="268" width="320" flashvars='config={"videoFile":"\1","autoPlay":false,"autoBuffering":false}' pluginspage="http://www.adobe.com/go/getflashplayer" type="application/x-shockwave-flash" bgcolor="#ffffff" quality="high" allowscriptaccess="always" allowfullscreen="true" src="/media/swf/FlowPlayerDark.swf"/>""" |
|---|
| 189 |
|
|---|
| 190 |
VIDEO_HELP = _("Link to any flash supported video") |
|---|
| 191 |
|
|---|
| 192 |
BUILTIN_PROTOCOLOS={ |
|---|
| 193 |
_('youtube'): (r'(.*)', YOUTUBE_STR, YOUTUBE_HELP), |
|---|
| 194 |
_('google_video'): (r'(.*)', GOOGLE_VIDEO_STR, GOOGLE_VIDEO_HELP), |
|---|
| 195 |
_('flickr'): (r'(.*)', FLICKR_STR, FLICKR_HELP), |
|---|
| 196 |
_('video'): (r'(.*)', VIDEO_STR, VIDEO_HELP), |
|---|
| 197 |
} |
|---|
| 198 |
|
|---|
| 199 |
class SpecialProtocolsPreProcessor(object): |
|---|
| 200 |
"Handles special protocols" |
|---|
| 201 |
|
|---|
| 202 |
def __init__(self): |
|---|
| 203 |
"Build a preprocessing regex" |
|---|
| 204 |
re_str = r"\|(%s)\|(.*?)\|" % '|'.join(BUILTIN_PROTOCOLOS.keys()) |
|---|
| 205 |
|
|---|
| 206 |
self.protocols_re = re.compile(re_str, re.UNICODE) |
|---|
| 207 |
|
|---|
| 208 |
def __call__(self, content): |
|---|
| 209 |
|
|---|
| 210 |
return self.protocols_re.sub( r'lahakprotocol__\1__\2__lahakprotocol', content ) |
|---|
| 211 |
|
|---|