"""Base class for all web GUI components."""
import re
from types import TupleType, ListType
from Mailman import mm_cfg
from Mailman import Utils
from Mailman import Errors
from Mailman.i18n import _
NL = '\n'
BADJOINER = '</code>, <code>'
class GUIBase:
def _getValidValue(self, mlist, property, wtype, val):
if wtype in (mm_cfg.Radio, mm_cfg.Toggle):
return int(val)
if wtype in (mm_cfg.String, mm_cfg.Text):
return val
if wtype == mm_cfg.Email:
if val:
Utils.ValidateEmail(val)
return val
if wtype in (mm_cfg.EmailList, mm_cfg.EmailListEx):
if isinstance(val, ListType):
return val
addrs = []
for addr in [s.strip() for s in val.split(NL)]:
if not addr:
continue
try:
Utils.ValidateEmail(addr)
except Errors.EmailAddressError:
if wtype == mm_cfg.EmailListEx and addr.startswith('^'):
try:
re.compile(addr)
except re.error:
raise ValueError
else:
raise
addrs.append(addr)
return addrs
if wtype == mm_cfg.Host:
return val
if wtype == mm_cfg.Number:
num = -1
try:
num = int(val)
except ValueError:
num = float(val)
if num < 0:
return getattr(mlist, property)
return num
if wtype == mm_cfg.Select:
return val
if wtype == mm_cfg.Checkbox:
if isinstance(val, ListType):
return val
return [val]
if wtype == mm_cfg.FileUpload:
return val
if wtype == mm_cfg.Topics:
return val
if wtype == mm_cfg.HeaderFilter:
return val
assert 0, 'Bad gui widget type: %s' % wtype
def _setValue(self, mlist, property, val, doc):
if not property.startswith('_') and getattr(mlist, property) <> val:
setattr(mlist, property, val)
def _postValidate(self, mlist, doc):
pass
def _escape(self, property, value):
value = value.replace('<', '<')
return value
def handleForm(self, mlist, category, subcat, cgidata, doc):
for item in self.GetConfigInfo(mlist, category, subcat):
if not isinstance(item, TupleType) or len(item) < 5:
continue
property, wtype, args, deps, desc = item[0:5]
uploadprop = property + '_upload'
if cgidata.has_key(uploadprop) and cgidata[uploadprop].value:
val = cgidata[uploadprop].value
elif not cgidata.has_key(property):
continue
elif isinstance(cgidata[property], ListType):
val = [self._escape(property, x.value)
for x in cgidata[property]]
else:
val = self._escape(property, cgidata[property].value)
try:
val = self._getValidValue(mlist, property, wtype, val)
except ValueError:
doc.addError(_('Invalid value for variable: %(property)s'))
except Errors.EmailAddressError:
doc.addError(
_('Bad email address for option %(property)s: %(val)s'))
else:
self._setValue(mlist, property, val, doc)
self._postValidate(mlist, doc)
def _convertString(self, mlist, property, alloweds, val, doc):
dollarp = getattr(mlist, 'use_dollar_strings', 0)
if dollarp:
ids = Utils.dollar_identifiers(val)
else:
ids = Utils.percent_identifiers(val)
for allowed in alloweds:
if ids.has_key(allowed):
del ids[allowed]
if ids:
badkeys = ids.keys()
badkeys.sort()
bad = BADJOINER.join(badkeys)
doc.addError(_(
"""The following illegal substitution variables were
found in the <code>%(property)s</code> string:
<code>%(bad)s</code>
<p>Your list may not operate properly until you correct this
problem."""), tag=_('Warning: '))
return val
if not dollarp:
fixed = Utils.to_percent(Utils.to_dollar(val))
if fixed <> val:
doc.addError(_(
"""Your <code>%(property)s</code> string appeared to
have some correctable problems in its new value.
The fixed value will be used instead. Please
double check that this is what you intended.
"""))
return fixed
return val