Skip to content

Commit c8bb309

Browse files
author
Richard Jones
committed
Centralised conversion of user-input data to hyperdb values
(bug [SF#802405], bug [SF#817217], rfe [SF#816994])
1 parent 92e6a72 commit c8bb309

File tree

8 files changed

+343
-242
lines changed

8 files changed

+343
-242
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ Fixed:
2828
- Date arithmetic was utterly broken, and has been for a long time.
2929
Date +/- Interval now works, and Date - Date also works (produces
3030
an Interval.
31+
- Centralised conversion of user-input data to hyperdb values (bug #802405,
32+
bug #817217, rfe #816994)
3133

3234
Cleanup:
3335
- Replace curuserid attribute on Database with the extended getuid() method.

roundup/admin.py

Lines changed: 10 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1717
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1818
#
19-
# $Id: admin.py,v 1.59 2003-10-24 19:48:05 jlgijsbers Exp $
19+
# $Id: admin.py,v 1.60 2003-11-11 00:35:13 richard Exp $
2020

2121
'''Administration commands for maintaining Roundup trackers.
2222
'''
@@ -569,42 +569,11 @@ def do_set(self, args, pwre = re.compile(r'{(\w+)}(.+)')):
569569

570570
properties = cl.getprops()
571571
for key, value in props.items():
572-
proptype = properties[key]
573-
if isinstance(proptype, hyperdb.Multilink):
574-
if value is None:
575-
props[key] = []
576-
else:
577-
props[key] = value.split(',')
578-
elif value is None:
579-
continue
580-
elif isinstance(proptype, hyperdb.String):
581-
continue
582-
elif isinstance(proptype, hyperdb.Password):
583-
m = pwre.match(value)
584-
if m:
585-
# password is being given to us encrypted
586-
p = password.Password()
587-
p.scheme = m.group(1)
588-
p.password = m.group(2)
589-
props[key] = p
590-
else:
591-
props[key] = password.Password(value)
592-
elif isinstance(proptype, hyperdb.Date):
593-
try:
594-
props[key] = date.Date(value)
595-
except ValueError, message:
596-
raise UsageError, '"%s": %s'%(value, message)
597-
elif isinstance(proptype, hyperdb.Interval):
598-
try:
599-
props[key] = date.Interval(value)
600-
except ValueError, message:
601-
raise UsageError, '"%s": %s'%(value, message)
602-
elif isinstance(proptype, hyperdb.Link):
603-
props[key] = value
604-
elif isinstance(proptype, hyperdb.Boolean):
605-
props[key] = value.lower() in ('yes', 'true', 'on', '1')
606-
elif isinstance(proptype, hyperdb.Number):
607-
props[key] = float(value)
572+
try:
573+
props[key] = hyperdb.rawToHyperdb(self.db, cl, itemid,
574+
key, value)
575+
except hyperdb.HyperdbValueError, message:
576+
raise UsageError, message
608577

609578
# try the set
610579
try:
@@ -777,39 +746,11 @@ def do_create(self, args, pwre = re.compile(r'{(\w+)}(.+)')):
777746

778747
# convert types
779748
for propname, value in props.items():
780-
# get the property
781749
try:
782-
proptype = properties[propname]
783-
except KeyError:
784-
raise UsageError, _('%(classname)s has no property '
785-
'"%(propname)s"')%locals()
786-
787-
if isinstance(proptype, hyperdb.Date):
788-
try:
789-
props[propname] = date.Date(value)
790-
except ValueError, message:
791-
raise UsageError, _('"%(value)s": %(message)s')%locals()
792-
elif isinstance(proptype, hyperdb.Interval):
793-
try:
794-
props[propname] = date.Interval(value)
795-
except ValueError, message:
796-
raise UsageError, _('"%(value)s": %(message)s')%locals()
797-
elif isinstance(proptype, hyperdb.Password):
798-
m = pwre.match(value)
799-
if m:
800-
# password is being given to us encrypted
801-
p = password.Password()
802-
p.scheme = m.group(1)
803-
p.password = m.group(2)
804-
props[propname] = p
805-
else:
806-
props[propname] = password.Password(value)
807-
elif isinstance(proptype, hyperdb.Multilink):
808-
props[propname] = value.split(',')
809-
elif isinstance(proptype, hyperdb.Boolean):
810-
props[propname] = value.lower() in ('yes', 'true', 'on', '1')
811-
elif isinstance(proptype, hyperdb.Number):
812-
props[propname] = float(value)
750+
props[key] = hyperdb.rawToHyperdb(self.db, cl, None,
751+
propname, value)
752+
except hyperdb.HyperdbValueError, message:
753+
raise UsageError, message
813754

814755
# check for the key property
815756
propname = cl.getkey()

roundup/cgi/client.py

Lines changed: 21 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: client.py,v 1.143 2003-10-24 09:32:19 jlgijsbers Exp $
1+
# $Id: client.py,v 1.144 2003-11-11 00:35:14 richard Exp $
22

33
__doc__ = """
44
WWW request handler (also used in the stand-alone server).
@@ -1675,51 +1675,18 @@ def parsePropsFromForm(self, num_re=re.compile('^\d+$')):
16751675
if value != confirm.value:
16761676
raise FormError, 'Password and confirmation text do '\
16771677
'not match'
1678-
value = password.Password(value)
1679-
1680-
elif isinstance(proptype, hyperdb.Link):
1681-
# see if it's the "no selection" choice
1682-
if value == '-1' or not value:
1683-
# if we're creating, just don't include this property
1684-
if not nodeid or nodeid.startswith('-'):
1685-
continue
1686-
value = None
1687-
else:
1688-
# handle key values
1689-
link = proptype.classname
1690-
if not num_re.match(value):
1691-
try:
1692-
value = db.classes[link].lookup(value)
1693-
except KeyError:
1694-
raise FormError, _('property "%(propname)s": '
1695-
'%(value)s not a %(classname)s')%{
1696-
'propname': propname, 'value': value,
1697-
'classname': link}
1698-
except TypeError, message:
1699-
raise FormError, _('you may only enter ID values '
1700-
'for property "%(propname)s": %(message)s')%{
1701-
'propname': propname, 'message': message}
1678+
try:
1679+
value = password.Password(value)
1680+
except hyperdb.HyperdbValueError, msg:
1681+
raise FormError, msg
1682+
17021683
elif isinstance(proptype, hyperdb.Multilink):
1703-
# perform link class key value lookup if necessary
1704-
link = proptype.classname
1705-
link_cl = db.classes[link]
1706-
l = []
1707-
for entry in value:
1708-
if not entry: continue
1709-
if not num_re.match(entry):
1710-
try:
1711-
entry = link_cl.lookup(entry)
1712-
except KeyError:
1713-
raise FormError, _('property "%(propname)s": '
1714-
'"%(value)s" not an entry of %(classname)s')%{
1715-
'propname': propname, 'value': entry,
1716-
'classname': link}
1717-
except TypeError, message:
1718-
raise FormError, _('you may only enter ID values '
1719-
'for property "%(propname)s": %(message)s')%{
1720-
'propname': propname, 'message': message}
1721-
l.append(entry)
1722-
l.sort()
1684+
# convert input to list of ids
1685+
try:
1686+
l = hyperdb.rawToHyperdb(self.db, cl, nodeid,
1687+
propname, value)
1688+
except hyperdb.HyperdbValueError, msg:
1689+
raise FormError, msg
17231690

17241691
# now use that list of ids to modify the multilink
17251692
if mlaction == 'set':
@@ -1753,13 +1720,10 @@ def parsePropsFromForm(self, num_re=re.compile('^\d+$')):
17531720
value.sort()
17541721

17551722
elif value == '':
1756-
# if we're creating, just don't include this property
1757-
if not nodeid or nodeid.startswith('-'):
1758-
continue
17591723
# other types should be None'd if there's no value
17601724
value = None
17611725
else:
1762-
# handle ValueErrors for all these in a similar fashion
1726+
# handle all other types
17631727
try:
17641728
if isinstance(proptype, hyperdb.String):
17651729
if (hasattr(value, 'filename') and
@@ -1777,23 +1741,17 @@ def parsePropsFromForm(self, num_re=re.compile('^\d+$')):
17771741
props['type'] = mimetypes.guess_type(fn)[0]
17781742
if not props['type']:
17791743
props['type'] = "application/octet-stream"
1780-
# finally, read the content
1744+
# finally, read the content RAW
17811745
value = value.value
17821746
else:
1783-
# normal String fix the CRLF/CR -> LF stuff
1784-
value = fixNewlines(value)
1747+
value = hyperdb.rawToHyperdb(self.db, cl,
1748+
nodeid, propname, value)
17851749

1786-
elif isinstance(proptype, hyperdb.Date):
1787-
value = date.Date(value, offset=timezone)
1788-
elif isinstance(proptype, hyperdb.Interval):
1789-
value = date.Interval(value)
1790-
elif isinstance(proptype, hyperdb.Boolean):
1791-
value = value.lower() in ('yes', 'true', 'on', '1')
1792-
elif isinstance(proptype, hyperdb.Number):
1793-
value = float(value)
1794-
except ValueError, msg:
1795-
raise FormError, _('Error with %s property: %s')%(
1796-
propname, msg)
1750+
else:
1751+
value = hyperdb.rawToHyperdb(self.db, cl, nodeid,
1752+
propname, value)
1753+
except hyperdb.HyperdbValueError, msg:
1754+
raise FormError, msg
17971755

17981756
# register that we got this property
17991757
if value:
@@ -1881,16 +1839,6 @@ def parsePropsFromForm(self, num_re=re.compile('^\d+$')):
18811839
raise FormError, _('File is empty')
18821840
return all_props, all_links
18831841

1884-
def fixNewlines(text):
1885-
''' Homogenise line endings.
1886-
1887-
Different web clients send different line ending values, but
1888-
other systems (eg. email) don't necessarily handle those line
1889-
endings. Our solution is to convert all line endings to LF.
1890-
'''
1891-
text = text.replace('\r\n', '\n')
1892-
return text.replace('\r', '\n')
1893-
18941842
def extractFormList(value):
18951843
''' Extract a list of values from the form value.
18961844

0 commit comments

Comments
 (0)