fix <optgroup> tag cannot be empty according to DTD
"""security management and error screens:organization: Logilab:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr"""__docformat__="restructuredtext en"_=unicodefromlogilab.mtconverterimporthtml_escapefromcubicweb.selectorsimportyes,none_rset,match_user_groupsfromcubicweb.viewimportAnyRsetView,StartupView,EntityViewfromcubicweb.common.uilibimporthtml_traceback,rest_tracebackfromcubicweb.webimportformwidgetsfromcubicweb.web.formimportFieldsForm,EntityFieldsFormfromcubicweb.web.formfieldsimportguess_fieldfromcubicweb.web.formrenderersimportHTableFormRendererSUBMIT_MSGID=_('Submit bug report')MAIL_SUBMIT_MSGID=_('Submit bug report by mail')classSecurityViewMixIn(object):"""display security information for a given schema """defschema_definition(self,eschema,link=True,access_types=None):w=self.w_=self.req._ifnotaccess_types:access_types=eschema.ACTIONSw(u'<table class="schemaInfo">')w(u'<tr><th>%s</th><th>%s</th><th>%s</th></tr>'%(_("permission"),_('granted to groups'),_('rql expressions')))foraccess_typeinaccess_types:w(u'<tr>')w(u'<td>%s</td>'%_('%s_perm'%access_type))groups=eschema.get_groups(access_type)l=[]groups=[(_(group),group)forgroupingroups]fortrad,groupinsorted(groups):iflink:l.append(u'<a href="%s" class="%s">%s</a><br/>'%(self.build_url('egroup/%s'%group),group,trad))else:l.append(u'<div class="%s">%s</div>'%(group,trad))w(u'<td>%s</td>'%u''.join(l))rqlexprs=eschema.get_rqlexprs(access_type)w(u'<td>%s</td>'%u'<br/><br/>'.join(expr.expressionforexprinrqlexprs))w(u'</tr>\n')w(u'</table>')defhas_schema_modified_permissions(self,eschema,access_types):""" return True if eschema's actual permissions are diffrents from the default ones """foraccess_typeinaccess_types:ifeschema.get_rqlexprs(access_type):returnTrueifeschema.get_groups(access_type)!= \frozenset(eschema.get_default_groups()[access_type]):returnTruereturnFalseclassSecurityManagementView(EntityView,SecurityViewMixIn):"""display security information for a given entity"""id='security'title=_('security')defcall(self):self.w(u'<div id="progress">%s</div>'%self.req._('validating...'))super(SecurityManagementView,self).call()defcell_call(self,row,col):self.req.add_js('cubicweb.edition.js')self.req.add_css('cubicweb.acl.css')entity=self.entity(row,col)w=self.w_=self.req._w(u'<h1><span class="etype">%s</span> <a href="%s">%s</a></h1>'%(entity.dc_type().capitalize(),html_escape(entity.absolute_url()),html_escape(entity.dc_title())))# first show permissions defined by the schemaself.w('<h2>%s</h2>'%_('schema\'s permissions definitions'))self.schema_definition(entity.e_schema)self.w('<h2>%s</h2>'%_('manage security'))# ownership informationifself.schema.rschema('owned_by').has_perm(self.req,'add',fromeid=entity.eid):self.owned_by_edit_form(entity)else:self.owned_by_information(entity)# cwpermissionsif'require_permission'inentity.e_schema.subject_relations():w('<h3>%s</h3>'%_('permissions for this entity'))reqpermschema=self.schema.rschema('require_permission')self.require_permission_information(entity,reqpermschema)ifreqpermschema.has_perm(self.req,'add',fromeid=entity.eid):self.require_permission_edit_form(entity)defowned_by_edit_form(self,entity):self.w('<h3>%s</h3>'%self.req._('ownership'))msg=self.req._('ownerships have been changed')form=EntityFieldsForm(self.req,None,entity=entity,submitmsg=msg,form_buttons=[formwidgets.SubmitButton()],domid='ownership%s'%entity.eid,__redirectvid='security',__redirectpath=entity.rest_path())field=guess_field(entity.e_schema,self.schema.rschema('owned_by'))form.append_field(field)self.w(form.form_render(display_progress_div=False))defowned_by_information(self,entity):ownersrset=entity.related('owned_by')ifownersrset:self.w('<h3>%s</h3>'%self.req._('ownership'))self.w(u'<div class="ownerInfo">')self.w(self.req._('this entity is currently owned by')+' ')self.wview('csv',entity.related('owned_by'),'null')self.w(u'</div>')# else we don't know if this is because entity has no owner or becayse# user as no access to owner users entitiesdefrequire_permission_information(self,entity,reqpermschema):ifentity.require_permission:w=self.w_=self.req._ifreqpermschema.has_perm(self.req,'delete',fromeid=entity.eid):delurl=self.build_url('edit',__redirectvid='security',__redirectpath=entity.rest_path())delurl=delurl.replace('%','%%')# don't give __delete value to build_url else it will be urlquoted# and this will replace %s by %25sdelurl+='&__delete=%s:require_permission:%%s'%entity.eiddellinktempl=u'[<a href="%s" title="%s">-</a>] '%(html_escape(delurl),_('delete this permission'))else:dellinktempl=Nonew(u'<table class="schemaInfo">')w(u'<tr><th>%s</th><th>%s</th></tr>'%(_("permission"),_('granted to groups')))forcwperminentity.require_permission:w(u'<tr>')ifdellinktempl:w(u'<td>%s%s</td>'%(dellinktempl%cwperm.eid,cwperm.view('oneline')))else:w(u'<td>%s</td>'%cwperm.view('oneline'))w(u'<td>%s</td>'%self.view('csv',cwperm.related('require_group'),'null'))w(u'</tr>\n')w(u'</table>')else:self.w(self.req._('no associated permissions'))defrequire_permission_edit_form(self,entity):w=self.w_=self.req._newperm=self.vreg.etype_class('CWPermission')(self.req,None)newperm.eid=self.req.varmaker.next()w(u'<p>%s</p>'%_('add a new permission'))form=EntityFieldsForm(self.req,None,entity=newperm,form_buttons=[formwidgets.SubmitButton()],domid='reqperm%s'%entity.eid,__redirectvid='security',__redirectpath=entity.rest_path())form.form_add_hidden('require_permission',entity.eid,role='object',eidparam=True)permnames=getattr(entity,'__permissions__',None)cwpermschema=newperm.e_schemaifpermnamesisnotNone:field=guess_field(cwpermschema,self.schema.rschema('name'),widget=formwidgets.Select({'size':1}),choices=permnames)else:field=guess_field(cwpermschema,self.schema.rschema('name'))form.append_field(field)field=guess_field(cwpermschema,self.schema.rschema('label'))form.append_field(field)field=guess_field(cwpermschema,self.schema.rschema('require_group'))form.append_field(field)self.w(form.form_render(renderer=HTableFormRenderer(display_progress_div=False)))classErrorView(AnyRsetView):"""default view when no result has been found"""__select__=yes()id='error'defpage_title(self):"""returns a title according to the result set - used for the title in the HTML header """returnself.req._('an error occured')defcall(self):req=self.req.reset_headers()w=self.wex=req.data.get('ex')#_("unable to find exception information"))excinfo=req.data.get('excinfo')title=self.req._('an error occured')w(u'<h2>%s</h2>'%title)if'errmsg'inreq.data:ex=req.data['errmsg']exclass=Noneelse:exclass=ex.__class__.__name__ex=exc_message(ex,req.encoding)ifexcinfoisnotNoneandself.config['print-traceback']:ifexclassisNone:w(u'<div class="tb">%s</div>'%html_escape(ex).replace("\n","<br />"))else:w(u'<div class="tb">%s: %s</div>'%(exclass,html_escape(ex).replace("\n","<br />")))w(u'<hr />')w(u'<div class="tb">%s</div>'%html_traceback(excinfo,ex,''))else:w(u'<div class="tb">%s</div>'%(html_escape(ex).replace("\n","<br />")))# if excinfo is not None, it's probably not a bugifexcinfoisNone:returnvcconf=self.config.vc_config()w(u"<div>")eversion=vcconf.get('cubicweb',self.req._('no version information'))# NOTE: tuple wrapping needed since eversion is itself a tuplew(u"<b>CubicWeb version:</b> %s<br/>\n"%(eversion,))cversions=[]forcubeinself.config.cubes():cubeversion=vcconf.get(cube,self.req._('no version information'))w(u"<b>Package %s version:</b> %s<br/>\n"%(cube,cubeversion))cversions.append((cube,cubeversion))w(u"</div>")# creates a bug submission link if SUBMIT_URL is setsubmiturl=self.config['submit-url']submitmail=self.config['submit-mail']ifsubmiturlorsubmitmail:form=FieldsForm(self.req,set_error_url=False)binfo=text_error_description(ex,excinfo,req,eversion,cversions)form.form_add_hidden('description',binfo)form.form_add_hidden('__bugreporting','1')ifsubmitmail:form.form_buttons=[formwidgets.SubmitButton(MAIL_SUBMIT_MSGID)]form.action=req.build_url('reportbug')w(form.form_render())ifsubmiturl:form.form_add_hidden('description_format','text/rest')form.form_buttons=[formwidgets.SubmitButton(SUBMIT_MSGID)]form.action=submiturlw(form.form_render())defexc_message(ex,encoding):try:returnunicode(ex)except:try:returnunicode(str(ex),encoding,'replace')except:returnunicode(repr(ex),encoding,'replace')deftext_error_description(ex,excinfo,req,eversion,cubes):binfo=rest_traceback(excinfo,html_escape(ex))binfo+=u'\n\n:URL: %s\n'%req.url()ifnot'__bugreporting'inreq.form:binfo+=u'\n:form params:\n'binfo+=u'\n'.join(u' * %s = %s'%(k,v)fork,vinreq.form.iteritems())binfo+=u'\n\n:CubicWeb version: %s\n'%(eversion,)forpkg,pkgversionincubes:binfo+=u":Package %s version: %s\n"%(pkg,pkgversion)binfo+='\n'returnbinfoclassProcessInformationView(StartupView):id='info'__select__=none_rset()&match_user_groups('managers')title=_('server information')defcall(self,**kwargs):"""display server information"""vcconf=self.config.vc_config()req=self.req_=req._# display main informationself.w(u'<h3>%s</h3>'%_('Application'))self.w(u'<table border="1">')self.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'%('CubicWeb',vcconf.get('cubicweb',_('no version information'))))forpkginself.config.cubes():pkgversion=vcconf.get(pkg,_('no version information'))self.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'%(pkg,pkgversion))self.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'%(_('home'),self.config.apphome))self.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'%(_('base url'),req.base_url()))self.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'%(_('data directory url'),req.datadir_url))self.w(u'</table>')self.w(u'<br/>')# environment and request and server informationtry:# need to remove our adapter and then modpython-apache wrapper...env=req._areq._req.subprocess_envexceptAttributeError:returnself.w(u'<h3>%s</h3>'%_('Environment'))self.w(u'<table border="1">')forattrinenv.keys():self.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'%(attr,html_escape(env[attr])))self.w(u'</table>')self.w(u'<h3>%s</h3>'%_('Request'))self.w(u'<table border="1">')forattrin('filename','form','hostname','main','method','path_info','protocol','search_state','the_request','unparsed_uri','uri'):val=getattr(req,attr)self.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'%(attr,html_escape(val)))self.w(u'</table>')server=req.serverself.w(u'<h3>%s</h3>'%_('Server'))self.w(u'<table border="1">')forattrindir(server):val=getattr(server,attr)ifattr.startswith('_')orcallable(val):continueself.w(u'<tr><th align="left">%s</th><td>%s</td></tr>'%(attr,html_escape(val)))self.w(u'</table>')