469 lines
16 KiB
Python
469 lines
16 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.
|
|
|
|
|
|
__doc__ = """Glasnost XHTML Generator"""
|
|
|
|
__version__ = '$Revision$'[11:-2]
|
|
|
|
|
|
import base64
|
|
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'),
|
|
'every-article': N_('Every Article'),
|
|
'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-definition': N_('Definition'),
|
|
'view-list': N_('List'),
|
|
'view-type': N_('Type'),
|
|
'view-utilization': N_('Utilization'),
|
|
'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 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 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 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 = glasnostUrl(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 addKeywords(self, keywords):
|
|
# The following code doesn't work when the keywords variables are too
|
|
# big:
|
|
# for name, value in keywords.items():
|
|
# self.args[name] = value
|
|
# return self
|
|
if not keywords:
|
|
return self
|
|
session = context.getVar('session')
|
|
if session is None:
|
|
# This case should not happen.
|
|
for name, value in keywords.items():
|
|
self.add(name, value)
|
|
return self
|
|
encodedKeywords = {}
|
|
for name, value in keywords.items():
|
|
if type(value) in [types.StringType, types.UnicodeType]:
|
|
encodedKeywords[name] = base64.encodestring(value)
|
|
else:
|
|
encodedKeywords[name] = value
|
|
session['keywords'] = encodedKeywords
|
|
session['isDirty'] = 1
|
|
return self.add('keywords', 1)
|
|
|
|
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 glasnostUrl(httpUrl):
|
|
dispatcherHostName = None
|
|
dispatcherPort = None
|
|
localId = None
|
|
role = None
|
|
|
|
def __init__(self, id = None, hostNameAndPort = None, hostName = None,
|
|
port = None, role = None, action = None, localId = None):
|
|
from tools import splitId
|
|
if id is not None:
|
|
hostNameAndPort, role, localId = splitId(id)
|
|
if hostNameAndPort is not None:
|
|
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('dispatcherId')
|
|
if dispatcherId is not None:
|
|
dispatcherHostName = extractApplicationHostName(dispatcherId)
|
|
self.dispatcherHostName = dispatcherHostName
|
|
if port is not None:
|
|
self.dispatcherPort = port
|
|
else:
|
|
dispatcherId = context.getVar('dispatcherId')
|
|
if dispatcherId is not None:
|
|
dispatcherPort = extractApplicationPort(dispatcherId)
|
|
self.dispatcherPort = dispatcherPort
|
|
if role is not None:
|
|
self.role = role
|
|
else:
|
|
serverRole = context.getVar('serverRole')
|
|
if serverRole is not None:
|
|
self.role = serverRole
|
|
if localId is not None:
|
|
self.localId = localId
|
|
self.action = action
|
|
|
|
def getPath(self, **keywords):
|
|
knownRoles = context.getVar('knownRoles')
|
|
id = 'glasnost://%s/%s/%s' % (
|
|
self.dispatcherHostName, self.role, self.localId)
|
|
### FIXME: why doens't this method use getUrlId() ?
|
|
### (or the other way)
|
|
if knownRoles and 'pagenames' in knownRoles:
|
|
from glasnost.proxy.tools import getProxyForServerRole
|
|
pageNamesProxy = getProxyForServerRole('pagenames')
|
|
if pageNamesProxy:
|
|
computedId = '/%s' % pageNamesProxy.getNameByMappedId(id)
|
|
if computedId[1:]:
|
|
if self.action:
|
|
computedId = computedId + '/%s' % self.action
|
|
return computedId
|
|
|
|
if self.role is not None:
|
|
role = self.role
|
|
else:
|
|
serverRole = context.getVar('serverRole')
|
|
if serverRole is not None:
|
|
role = serverRole
|
|
else:
|
|
role = None
|
|
if knownRoles and not role in knownRoles:
|
|
return ''
|
|
raise Exception('Unknown server role = %s' % role)
|
|
|
|
httpScriptDirectoryPath = context.getVar(
|
|
'httpScriptDirectoryPath')
|
|
if httpScriptDirectoryPath is None:
|
|
httpScriptDirectoryPath = '/'
|
|
dispatcherId = context.getVar('dispatcherId')
|
|
if dispatcherId is not None:
|
|
dispatcherHostName = extractApplicationHostName(dispatcherId)
|
|
dispatcherPort = extractApplicationPort(dispatcherId)
|
|
else:
|
|
dispatcherHostName = None
|
|
dispatcherPort = None
|
|
if (self.dispatcherHostName is None \
|
|
or self.dispatcherHostName == dispatcherHostName) \
|
|
and (self.dispatcherPort is None \
|
|
or self.dispatcherPort == dispatcherPort):
|
|
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%s' % (
|
|
httpScriptDirectoryPath, role, self.localId, action)
|
|
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)
|
|
if self.action:
|
|
action = '/%s' % self.action
|
|
else:
|
|
action = ''
|
|
return '%s%s/glasnost/%s/%s%s' % (
|
|
httpScriptDirectoryPath, role,
|
|
dispatcherHostNameAndPort, self.localId, action)
|
|
|
|
|
|
def url(url):
|
|
if url.startswith('glasnost://'):
|
|
return glasnostUrl(id = url)
|
|
else:
|
|
parsedUrl = urlparse.urlparse(url)
|
|
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)
|
|
|