diff -r 000000000000 -r b97547f5f1fa web/views/embedding.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/views/embedding.py Wed Nov 05 15:52:50 2008 +0100 @@ -0,0 +1,164 @@ +"""Objects interacting together to provides the external page embeding +functionality. + + +:organization: Logilab +:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr +""" +__docformat__ = "restructuredtext en" + +import re +from urlparse import urljoin +from urllib2 import urlopen, Request, HTTPError + +from logilab.mtconverter import guess_encoding + +from cubicweb import urlquote # XXX should use view.url_quote method +from cubicweb.interfaces import IEmbedable +from cubicweb.common.uilib import soup2xhtml +from cubicweb.common.selectors import (onelinerset_selector, score_entity_selector, + searchstate_selector, interface_selector) +from cubicweb.common.view import NOINDEX, NOFOLLOW +from cubicweb.web.controller import Controller +from cubicweb.web.action import Action +from cubicweb.web.views import basetemplates + + +class ExternalTemplate(basetemplates.TheMainTemplate): + """template embeding an external web pages into CubicWeb web interface + """ + id = 'external' + + def call(self, body): + # XXX fallback to HTML 4 mode when embeding ? + self.set_request_content_type() + self.process_rql(self.req.form.get('rql')) + self.req.search_state = ('normal',) + self.template_header(self.content_type, None, self.req._('external page'), + [NOINDEX, NOFOLLOW]) + self.content_header() + self.w(body) + self.content_footer() + self.template_footer() + + +class EmbedController(Controller): + id = 'embed' + template = 'external' + + def publish(self, rset=None): + req = self.req + if 'custom_css' in req.form: + req.add_css(req.form['custom_css']) + embedded_url = req.form['url'] + allowed = self.config['embed-allowed'] + _ = req._ + if allowed is None or not allowed.match(embedded_url): + body = '

%s

%s

' % ( + _('error while embedding page'), + _('embedding this url is forbidden')) + else: + prefix = req.build_url(self.id, url='') + authorization = req.get_header('Authorization') + if authorization: + headers = {'Authorization' : authorization} + else: + headers = {} + try: + body = embed_external_page(embedded_url, prefix, + headers, req.form.get('custom_css')) + body = soup2xhtml(body, self.req.encoding) + except HTTPError, err: + body = '

%s

%s

' % ( + _('error while embedding page'), err) + return self.vreg.main_template(req, self.template, body=body) + + +class EmbedAction(Action): + """display an 'embed' link on entity implementing `embeded_url` method + if the returned url match embeding configuration + """ + id = 'embed' + controller = 'embed' + __selectors__ = (onelinerset_selector, searchstate_selector, + interface_selector, score_entity_selector) + accepts_interfaces = (IEmbedable,) + + title = _('embed') + + @classmethod + def score_entity(cls, entity): + """return a score telling how well I can display the given + entity instance (required by the value_selector) + """ + url = entity.embeded_url() + if not url or not url.strip(): + return 0 + allowed = cls.config['embed-allowed'] + if allowed is None or not allowed.match(url): + return 0 + return 1 + + def url(self, row=0): + entity = self.rset.get_entity(row, 0) + url = urljoin(self.req.base_url(), entity.embeded_url()) + if self.req.form.has_key('rql'): + return self.build_url(url=url, rql=self.req.form['rql']) + return self.build_url(url=url) + + + +# functions doing necessary substitutions to embed an external html page ###### + + +BODY_RGX = re.compile('(.*?)', re.I | re.S | re.U) +HREF_RGX = re.compile('