This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/shared/common/xhtmlgenerator.py

777 lines
27 KiB
Python

# -*- coding: iso-8859-15 -*-
# Glasnost
# By: Odile Bénassy <obenassy@entrouvert.com>
# Romain Chantereau <rchantereau@entrouvert.com>
# Nicolas Clapiès <nclapies@easter-eggs.org>
# Pierre-Antoine Dejace <padejace@entrouvert.be>
# Thierry Dulieu <tdulieu@easter-eggs.com>
# Florent Monnier <monnier@codelutin.com>
# Cédric Musso <cmusso@easter-eggs.org>
# Frédéric Péters <fpeters@entrouvert.be>
# Benjamin Poussin <poussin@codelutin.com>
# Emmanuel Raviart <eraviart@entrouvert.com>
# Sébastien Régnier <regnier@codelutin.com>
# Emmanuel Saracco <esaracco@easter-eggs.com>
#
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
# Emmanuel Saracco & Théridion
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
# Régnier, Emmanuel Saracco, Théridion & Vecam
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
from __future__ import nested_scopes
__doc__ = """Glasnost XHTML Generator"""
__version__ = '$Revision$'[11:-2]
import base64
import locale
import urlparse
from tools import extractApplicationHostName, extractApplicationPort
import context
from XhtmlGenerator import *
buttonLabels = {
'about': N_('About Glasnost'),
'abstain': N_('Abstain'),
'add': N_('Add'),
'add-article': N_('Add Article'),
'add-candidate': N_('Add Candidate'),
'apply': N_('Apply'),
'back': N_('Back'),
'cancel': N_('Cancel'),
'change-password': N_('Change Password'),
'change-translation': N_('Change Translation'),
'clone': N_('Duplicate'),
'compute': N_('Compute'),
'create': N_('Create'),
'delete': N_('Delete'),
'diff': N_('Differences'),
'download': N_('Download Glasnost'),
'edit': N_('Edit'),
'edit-arguments': N_('Edit Arguments'),
'evaluate': N_('Evaluate'),
'all-articles': N_('All Articles'),
'find': N_('Find'),
'history': N_('History'),
'implement': N_('New Implementation'),
'license': N_('Read the License'),
'login': N_('Login'),
'logout': N_('Exit'),
'modify': N_('Modify'),
'next': N_('Next'),
'new': N_('New'),
'new-account': N_('New Account'),
'ok': N_('OK'),
'pester-abstentionnists': N_('Pester Absentionnists'),
'post-comment': N_('Post a Comment'),
'post-reply': N_('Reply'),
'prefs': N_('Preferences'),
'pretion': N_('Pretion'),
'preview': N_('Preview'),
'propose': N_('Submit For Evaluation'),
'refuse': N_('Refuse'),
'send-by-email': N_('Send by Email'),
'send-password-by-email': N_('Send Password by Email'),
'settings': N_('Settings'),
'spell': N_('Spell Check'),
'source': N_('Source'),
'translate': N_('Translate'),
'update-translation': N_('Update Translation'),
'use': N_('Use'),
'validate': N_('Validate'),
'version': N_('Version'),
'view': N_('View'),
'view-definition': N_('Definition'),
'view-list': N_('List'),
'view-type': N_('Type'),
'view-widget': N_('Widget'),
'vote': N_('Vote '),
'vote-blank': N_('Vote Blank'),
}
class accountingCell(td):
def __init__(self, text = '', **attributes):
td.__init__(self, **attributes)
self.append(text)
self.text = text
def getText(self):
return self.text
class accountingTable(table):
def __init__(self, top = '', row=[]):
self.top = top
self.row = row
def getAsXml(self):
numCols = max(1, len(self.row))
topTd = td(colspan = numCols)
topTd.append([nbsp] * 4)
topTd.append(self.top)
topTr = tr(topTd)
rowTr = tr(self.row)
return table(topTr, rowTr).getAsXml()
class buttonAction:
label = None
def getAsXml(self, **keywords):
# Note: onSubmit doesn't seem to work and I don't know why.
layout = form(
_class = 'urls-choice', action= '/load',
method = 'post', name = 'urls-choice',
onSubmit = 'location.href = this.form.urlsChoice.options['
'this.form.urlsChoice.selectedIndex].value')
menu = select(
name = 'urlsChoice',
onChange = 'location.href = this.form.urlsChoice.options['
'this.form.urlsChoice.selectedIndex].value')
for labelAndLink in self.getLabelsAndLinks():
menu.append(option(value = labelAndLink[1])(labelAndLink[0]))
layout.append(menu)
layout.append(input(_class = 'button', type = 'submit',
value = _(self.label)))
return layout.getAsXml(**keywords)
class buttonInForm:
key = None
name = None
def __init__(self, key, name):
self.key = key
self.name = name
def getAsXml(self, **keywords):
if buttonLabels.has_key(self.key):
text = _(buttonLabels[self.key]).strip()
else:
text = self.key
trueTag = input(_class = 'button', name = self.name,
type = 'submit', value = text)
# The following solutions don't work with Internet Explorer.
## trueTag = button(_class = 'button', name = 'button',
## type = 'submit', value = self.name)(text)
## trueTag = button(_class = 'button', name = self.name,
## type = 'submit', value = self.name)(text)
return trueTag.getAsXml(**keywords)
class buttonGotoObjects(buttonAction):
label = N_('Go')
def getLabelsAndLinks(self):
from glasnost.web.tools import getGotoObjectsLabelsAndLinks
return getGotoObjectsLabelsAndLinks()
class buttonNewObject(buttonAction):
label = N_('Add')
def getLabelsAndLinks(self):
from glasnost.web.tools import getNewObjectLabelsAndLinks
return getNewObjectLabelsAndLinks()
class buttonPopup:
href = None
key = None
def __init__(self, key, href):
self.key = key
self.href = href
def getAsXml(self, **keywords):
if buttonLabels.has_key(self.key):
text = _(buttonLabels[self.key]).strip()
else:
text = self.key
jScript = "window.open('%s','comment','toolbar=no,location=no,"\
"directories=no,status=no,menubar=no,scrollbars=yes,"\
"width=566,height=333'); return false;" % self.href
trueTag = a(_class = 'button', href = self.href, OnClick=jScript)(text)
return trueTag.getAsXml(**keywords)
class buttonStandalone:
href = None
key = None
def __init__(self, key, href):
self.key = key
self.href = href
def getAsXml(self, **keywords):
if buttonLabels.has_key(self.key):
text = _(buttonLabels[self.key]).strip()
else:
text = self.key
trueTag = a(_class = 'button', href = self.href)(text)
return trueTag.getAsXml(**keywords)
def hContext():
sectionLevel = context.getVar('sectionLevel')
return globals()['h%d' % (sectionLevel+1)]
class menuIds:
attributes = {}
fieldValue = None
menus = None
roles = None
noneLabel = N_('None')
permanentIds = None
def __init__(self, roles, attributes = None, fieldValue = None,
fullRoles = None, menus = None, noneLabel = None,
permanentIds = None):
from glasnost.proxy.tools import getObjectLabelsTranslated, \
getProxyForServerRole
self.roles = roles
if attributes:
self.attributes = attributes
if fieldValue is not None:
self.fieldValue = fieldValue
if menus is None:
self.menus = {}
else:
self.menus = menus
if noneLabel is not None:
self.noneLabel = noneLabel
if permanentIds is not None:
self.permanentIds = permanentIds
if not self.menus:
for role in self.roles:
if not role:
continue
if fullRoles is not None and not role in fullRoles:
continue
proxy = getProxyForServerRole(role)
objectIds = proxy.getObjectIds()
if role == 'groups':
acceptedObjectIds = []
for objectId in objectIds:
accepted = 0
if not proxy.canGetObject(objectId):
objectIds.remove(objectId)
continue
object = proxy.getObject(objectId)
objectAcceptedRoles = object.getSlot(
'acceptedRoles').getValue()
if not objectAcceptedRoles:
accepted = 1
else:
for remainingRole in self.roles:
if remainingRole == 'groups':
continue
if remainingRole in objectAcceptedRoles:
accepted = 1
if accepted:
acceptedObjectIds.append(objectId)
objectIds = acceptedObjectIds
self.menus[role] = getObjectLabelsTranslated(
objectIds, context.getVar('readLanguages'))
user = context.getVar('user')
if user:
objectsMemory = user.objectsMemory
if objectsMemory is not None:
for role in self.roles:
if not objectsMemory.has_key(role):
continue
serverMemory = objectsMemory[role]
if not serverMemory:
continue
if self.menus.has_key(role):
continue
self.menus[role] = getObjectLabelsTranslated(
serverMemory,
context.getVar('readLanguages'))
def getAsXml(self, **keywords):
from glasnost.proxy.tools import getObjectLabelTranslated
from glasnost.web.tools import getWebForServerRole
selectLayout = select(**self.attributes)
optionAttributes = {}
if not self.fieldValue:
optionAttributes['selected'] = 'selected'
selectLayout += option(value = '', **optionAttributes)(
_(self.noneLabel))
if self.fieldValue:
objectId = self.fieldValue
try:
objectLabel = getObjectLabelTranslated(objectId,
context.getVar('readLanguages'))
except: # TODO: tighter check
pass
else:
selectLayout += option(selected = 'selected',
value = objectId)(objectLabel)
if self.permanentIds:
for permanentId in self.permanentIds:
if permanentId == self.fieldValue:
continue
try:
permanentLabel = getObjectLabelTranslated(permanentId,
context.getVar('readLanguages'))
except: # TODO: tighter check
pass
else:
selectLayout += option(value = permanentId)(permanentLabel)
usedRoles = []
roleLocalizedLabels = {}
for role in self.roles:
web = getWebForServerRole(role)
if not web:
continue
if not self.menus.has_key(role):
continue
menu = self.menus[role]
if not menu or len(menu) == 1 and menu.has_key(self.fieldValue):
continue
usedRoles.append(role)
roleLocalizedLabels[role] = _(web.objectsNameCapitalized)
usedRoles.sort(
lambda x, y:
locale.strcoll(roleLocalizedLabels[x], roleLocalizedLabels[y]))
for role in usedRoles:
menu = self.menus[role]
if len(self.menus) > 1:
optionsGroup = optgroup(label = roleLocalizedLabels[role])
selectLayout += optionsGroup
else:
optionsGroup = selectLayout
menuItems = menu.items()
menuItems.sort(lambda x,y:
locale.strcoll(x[1].lower(), y[1].lower()))
for objectId, objectLabel in menuItems:
if objectId == self.fieldValue:
continue
if len(objectLabel) > 80:
objectLabel = objectLabel[
: 70 + objectLabel[70:].find(' ')] + ' (...)'
optionsGroup += option(value = objectId)(objectLabel)
return selectLayout.getAsXml(**keywords)
def objectHypertextLabel(objectId):
import faults
from glasnost.proxy.tools import getObjectLabelTranslated
if not objectId:
return ''
try:
label = getObjectLabelTranslated(
objectId, context.getVar('readLanguages'))
except faults.MissingItem:
return span(_class = 'deleted')(_('Missing Object (%s)') % objectId)
return a(href = idUrl(objectId))(label)
class smallAccountingTable(table):
def __init__(self, side, amount=0):
assert (side=='debit' or side=='credit')
self.amount = str(amount)
self.side = side
def getAsXml(self, parent = None, indent = 0, **keywords):
width = 12
td1 = td(width=width)(self.amount)
td2 = td(width=width)(nbsp)
r = tr()
if self.side == 'debit':
r.append(td1)
r.append(td2)
else:
r.append(td2)
r.append(td1)
return table(r).getAsXml()
_httpUrl = httpUrl
class httpUrl(httpUrl):
pathPrefix = None
def __init__(self, protocol = None, hostNameAndPort = None,
hostName = None, port = None, path = None, parameters = None,
query = None, fragment = None):
httpScriptDirectoryPath = context.getVar(
'httpScriptDirectoryPath')
if httpScriptDirectoryPath is not None:
self.pathPrefix = httpScriptDirectoryPath
_httpUrl.__init__(
self, protocol = protocol, hostNameAndPort = hostNameAndPort,
hostName = hostName, port = port, path = path,
parameters = parameters, query = query, fragment = fragment)
def getArgumentNames(self):
argumentNames = _httpUrl.getArgumentNames(self)
canUseCookie = context.getVar('canUseCookie', default = 0)
sessionToken = context.getVar('sessionToken')
if not canUseCookie:
if sessionToken is not None \
and not 'sessionToken' in argumentNames:
argumentNames.append('sessionToken')
elif 'sessionToken' in argumentNames:
argumentNames.remove('sessionToken')
return argumentNames
def getArguments(self):
canUseCookie = context.getVar('canUseCookie', default = 0)
sessionToken = context.getVar('sessionToken')
if not canUseCookie:
if sessionToken is not None:
self.argument_sessionToken = sessionToken
arguments = _httpUrl.getArguments(self)
if not canUseCookie:
if sessionToken is not None:
del self.argument_sessionToken
return arguments
def getPath(self, **keywords):
if self.pathPrefix is not None:
pathPrefix = self.pathPrefix
else:
pathPrefix = context.getVar(
'httpScriptDirectoryPath')
if pathPrefix is None:
pathPrefix = '/'
path = _httpUrl.getPath(self, **keywords)
if path and path[0] == '/':
path = path[1:]
path = '%s%s' % (pathPrefix, path)
return path
class rootUrl(httpUrl):
dispatcherHostName = None
dispatcherPort = None
def __init__(self, hostNameAndPort = None, hostName = None, port = None):
if hostNameAndPort:
infos = hostNameAndPort.split(':', 1)
hostName = infos[0]
if len(infos) < 2:
port = None
else:
port = infos[1]
if hostName is not None:
self.dispatcherHostName = hostName
else:
dispatcherId = context.getVar('defaultDispatcherId')
if dispatcherId is None:
dispatcherId = context.getVar('dispatcherId')
if dispatcherId is not None:
dispatcherHostName = extractApplicationHostName(dispatcherId)
self.dispatcherHostName = dispatcherHostName
if port is not None:
self.dispatcherPort = str(port)
else:
dispatcherId = context.getVar('defaultDispatcherId')
if dispatcherId is None:
dispatcherId = context.getVar('dispatcherId')
if dispatcherId is not None:
dispatcherPort = str(extractApplicationPort(dispatcherId))
self.dispatcherPort = dispatcherPort
def getPath(self, **keywords):
httpScriptDirectoryPath = context.getVar('httpScriptDirectoryPath')
if httpScriptDirectoryPath is None:
httpScriptDirectoryPath = '/'
dispatcherId = context.getVar('defaultDispatcherId')
if dispatcherId is None:
dispatcherId = context.getVar('dispatcherId')
if dispatcherId is not None:
dispatcherHostName = extractApplicationHostName(dispatcherId)
dispatcherPort = str(extractApplicationPort(dispatcherId))
else:
dispatcherHostName = None
dispatcherPort = None
if self.dispatcherHostName == 'system' or (
(self.dispatcherHostName is None
or self.dispatcherHostName == dispatcherHostName)
and (self.dispatcherPort is None
or self.dispatcherPort == dispatcherPort)):
if context.getVar('languageSetInUrl') and \
not 'ignoreLanguage' in keywords.keys():
return httpScriptDirectoryPath + \
context.getVar('readLanguages')[0] + '/'
return httpScriptDirectoryPath
else:
if self.dispatcherHostName is not None:
dispatcherHostName = self.dispatcherHostName
elif dispatcherHostName is None:
dispatcherHostName = 'localhost'
if self.dispatcherPort is not None:
dispatcherPort = self.dispatcherPort
if dispatcherPort is None \
or dispatcherPort == str(context.getVar('dispatcherPort')):
dispatcherHostNameAndPort = dispatcherHostName
else:
dispatcherHostNameAndPort = '%s:%s' % (
dispatcherHostName, dispatcherPort)
result = '%sremote/%s/' % (
httpScriptDirectoryPath, dispatcherHostNameAndPort)
if context.getVar('languageSetInUrl') and \
not 'ignoreLanguage' in keywords.keys():
result += context.getVar('readLanguages')[0] + '/'
return result
class aliasUrl(rootUrl):
action = None
alias = None
def __init__(self, alias, action = None):
import tools_new as commonTools
dispatcherId = context.getVar('defaultDispatcherId')
if dispatcherId is None:
dispatcherId = context.getVar('dispatcherId')
hostNameAndPort = commonTools.extractHostNameAndPort(dispatcherId)
rootUrl.__init__(self, hostNameAndPort = hostNameAndPort)
assert alias
self.alias = alias
if action:
self.action = action
def getPath(self, **keywords):
path = rootUrl.getPath(self, **keywords)
templatePrefix = context.getVar('templatePrefix')
if templatePrefix:
if self.action:
action = '/%s%s' % (templatePrefix, self.action)
else:
action = '/%sview' % templatePrefix
else:
if self.action:
action = '/%s' % self.action
else:
action = ''
return '%s%s%s' % (path, self.alias, action)
class fileUrl(rootUrl):
filename = None
def __init__(self, filename):
rootUrl.__init__(self)
self.filename = filename
def getPath(self, **keywords):
path = rootUrl.getPath(self, ignoreLanguage = 1, **keywords)
if path[-1] == '/' and self.filename[0] == '/':
path = path[:-1]
return path + self.filename
class idUrl(rootUrl):
action = None
localId = None
role = None
id = None
def __init__(self, id, action = None):
import tools_new as commonTools
if id:
role = commonTools.extractRole(id)
localId = commonTools.extractLocalId(id)
self.id = id
else:
id = context.getVar('defaultDispatcherId')
if id is None:
id = context.getVar('dispatcherId')
role = context.getVar('serverRole')
localId = None
hostNameAndPort = commonTools.extractHostNameAndPort(id)
rootUrl.__init__(self, hostNameAndPort = hostNameAndPort)
if role:
self.role = role
if localId:
self.localId = localId
if action:
self.action = action
def getPath(self, **keywords):
try:
from glasnost.web.tools import getWebForServerRole
roleWeb = getWebForServerRole(self.role)
except ImportError:
roleWeb = None
if roleWeb and hasattr(roleWeb, 'idUrl') and (
not keywords or not keywords.has_key('ignoreWeb')):
return roleWeb.idUrl(self)
knownRoles = context.getVar('knownRoles')
if knownRoles and 'pagenames' in knownRoles:
from glasnost.proxy.tools import getProxyForServerRole
pageNamesProxy = getProxyForServerRole('pagenames')
if pageNamesProxy:
dispatcherId = context.getVar('defaultDispatcherId')
defaultDispatcherId = context.getVar('defaultDispatcherId')
if defaultDispatcherId is None:
defaultDispatcherId = context.getVar('dispatcherId')
if defaultDispatcherId is not None \
and defaultDispatcherId != dispatcherId:
# This is a remote id. Search for a local alias.
applicationId = commonTools.makeApplicationId(
defaultDispatcherId, self.role)
if self.localId:
id = '%s/%s' % (applicationId, self.localId)
else:
id = applicationId
try:
alias = pageNamesProxy.getNameByMappedId(id)
except faults.UnknownServerId:
alias = None
if alias:
return aliasUrl(alias, self.action).getPath()
path = rootUrl.getPath(self, **keywords)
templatePrefix = context.getVar('templatePrefix')
if templatePrefix:
if self.action:
action = '/%s%s' % (templatePrefix, self.action)
else:
action = '/%sview' % templatePrefix
else:
if self.action:
action = '/%s' % self.action
else:
action = ''
if knownRoles and 'pagenames' in knownRoles and pageNamesProxy:
if dispatcherId is None:
dispatcherId = context.getVar('dispatcherId')
if dispatcherId is not None:
applicationId = commonTools.makeApplicationId(
dispatcherId, self.role)
if self.localId:
id = '%s/%s' % (applicationId, self.localId)
else:
id = applicationId
try:
alias = pageNamesProxy.getNameByMappedId(id)
except faults.UnknownServerId:
alias = None
if alias:
return aliasUrl(alias, self.action).getPath()
dispatcherId = 'glasnost://%s' % self.dispatcherHostName
applicationId = commonTools.makeApplicationId(
dispatcherId, self.role)
if self.localId:
id = '%s/%s' % (applicationId, self.localId)
else:
id = applicationId
alias = pageNamesProxy.getNameByMappedId(id)
if alias:
return '%s%s%s' % (path, alias, action)
if self.role:
role = self.role
else:
role = ''
if self.localId:
localId = '/%s' % self.localId
else:
localId = ''
return '%s%s%s%s' % (path, role, localId, action)
def absoluteUrl(s):
if s.startswith('glasnost://'):
return idUrl(s)
else:
assert s.startswith('http')
return url(s)
def actionUrl(action = None):
return idUrl(None, action)
def roleUrl(role, action = None):
dispatcherId = context.getVar('defaultDispatcherId')
if dispatcherId is None:
dispatcherId = context.getVar('dispatcherId')
if not role:
role = context.getVar('serverRole')
serverId = commonTools.makeApplicationId(dispatcherId, role)
return idUrl(serverId, action)
def url(s):
parsedUrl = urlparse.urlparse(s)
if parsedUrl[0]:
protocol = parsedUrl[0]
else:
protocol = None
if parsedUrl[1]:
hostNameAndPort = parsedUrl[1]
else:
hostNameAndPort = None
if parsedUrl[2]:
path = parsedUrl[2]
else:
path = None
if parsedUrl[3]:
parameters = parsedUrl[3]
else:
parameters = None
if parsedUrl[4]:
query = parsedUrl[4]
else:
query = None
if parsedUrl[5]:
fragment = parsedUrl[5]
else:
fragment = None
return httpUrl(
protocol = protocol, hostNameAndPort = hostNameAndPort,
path = path, parameters = parameters, query = query,
fragment = fragment)