update _render_attribute / _render_relation prototype to gain more control on label through uicfg (for attributes and relations). Keep bw compat for crm/iliane
"""Objects interacting together to provides the external page embedingfunctionality.:organization: Logilab:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"importrefromurlparseimporturljoinfromurllib2importurlopen,Request,HTTPErrorfromlogilab.mtconverterimportguess_encodingfromcubicwebimporturlquote# XXX should use view.url_quote methodfromcubicweb.selectorsimport(one_line_rset,score_entity,match_search_state,implements)fromcubicweb.interfacesimportIEmbedablefromcubicweb.viewimportNOINDEX,NOFOLLOWfromcubicweb.common.uilibimportsoup2xhtmlfromcubicweb.web.controllerimportControllerfromcubicweb.web.actionimportActionfromcubicweb.web.viewsimportbasetemplatesclassExternalTemplate(basetemplates.TheMainTemplate):"""template embeding an external web pages into CubicWeb web interface """id='external'defcall(self,body):# XXX fallback to HTML 4 mode when embeding ?self.set_request_content_type()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()classEmbedController(Controller):id='embed'template='external'defpublish(self,rset=None):req=self.reqif'custom_css'inreq.form:req.add_css(req.form['custom_css'])embedded_url=req.form['url']allowed=self.config['embed-allowed']_=req._ifallowedisNoneornotallowed.match(embedded_url):body='<h2>%s</h2><h3>%s</h3>'%(_('error while embedding page'),_('embedding this url is forbidden'))else:prefix=req.build_url(self.id,url='')authorization=req.get_header('Authorization')ifauthorization: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)exceptHTTPError,err:body='<h2>%s</h2><h3>%s</h3>'%(_('error while embedding page'),err)self.process_rql(req.form.get('rql'))returnself.vreg['views'].main_template(req,self.template,rset=self.rset,body=body)defentity_has_embedable_url(entity):"""return 1 if the entity provides an allowed embedable url"""url=entity.embeded_url()ifnoturlornoturl.strip():return0allowed=entity.config['embed-allowed']ifallowedisNoneornotallowed.match(url):return0return1classEmbedAction(Action):"""display an 'embed' link on entity implementing `embeded_url` method if the returned url match embeding configuration """id='embed'__select__=(one_line_rset()&match_search_state('normal')&implements(IEmbedable)&score_entity(entity_has_embedable_url))title=_('embed')controller='embed'defurl(self,row=0):entity=self.rset.get_entity(row,0)url=urljoin(self.req.base_url(),entity.embeded_url())ifself.req.form.has_key('rql'):returnself.build_url(url=url,rql=self.req.form['rql'])returnself.build_url(url=url)# functions doing necessary substitutions to embed an external html page ######BODY_RGX=re.compile('<body.*?>(.*?)</body>',re.I|re.S|re.U)HREF_RGX=re.compile('<a\s+href="([^"]*)"',re.I|re.S|re.U)SRC_RGX=re.compile('<img\s+src="([^"]*)"',re.I|re.S|re.U)classreplace_href:def__init__(self,prefix,custom_css=None):self.prefix=prefixself.custom_css=custom_cssdef__call__(self,match):original_url=match.group(1)url=self.prefix+urlquote(original_url,safe='')ifself.custom_cssisnotNone:if'?'inurl:url='%s&custom_css=%s'%(url,self.custom_css)else:url='%s?custom_css=%s'%(url,self.custom_css)return'<a href="%s"'%urlclassabsolutize_links:def__init__(self,embedded_url,tag,custom_css=None):self.embedded_url=embedded_urlself.tag=tagself.custom_css=custom_cssdef__call__(self,match):original_url=match.group(1)if'://'inoriginal_url:returnmatch.group(0)# leave it unchangedreturn'%s="%s"'%(self.tag,urljoin(self.embedded_url,original_url))defprefix_links(body,prefix,embedded_url,custom_css=None):filters=((HREF_RGX,absolutize_links(embedded_url,'<a href',custom_css)),(SRC_RGX,absolutize_links(embedded_url,'<img src')),(HREF_RGX,replace_href(prefix,custom_css)))forrgx,replinfilters:body=rgx.sub(repl,body)returnbodydefembed_external_page(url,prefix,headers=None,custom_css=None):req=Request(url,headers=(headersor{}))content=urlopen(req).read()page_source=unicode(content,guess_encoding(content),'replace')page_source=page_sourcematch=BODY_RGX.search(page_source)ifmatchisNone:returnpage_sourcereturnprefix_links(match.group(1),prefix,url,custom_css)