@@ -81,6 +81,29 @@ def _field_upload_text(cgidata, fieldname):
8181 return cgidata .getfirst (fieldname , '' ) or ''
8282
8383
84+ def _member_field_keys (user , suffix ):
85+ """Return possible form keys for a per-member field.
86+
87+ Member list forms use multipart encoding with URL-quoted addresses in
88+ field names. Depending on the browser and encoder, submitted keys may
89+ still contain percent escapes or may already be decoded. Urlencoded
90+ posts are always decoded by parse_qs.
91+ """
92+ return ('%s_%s' % (user , suffix ),
93+ '%s_%s' % (urllib .parse .quote (user ), suffix ))
94+
95+
96+ def _member_field_in_cgidata (cgidata , user , suffix ):
97+ return any (k in cgidata for k in _member_field_keys (user , suffix ))
98+
99+
100+ def _member_field_getfirst (cgidata , user , suffix , default = None ):
101+ for key in _member_field_keys (user , suffix ):
102+ if key in cgidata :
103+ return cgidata .getfirst (key , default )
104+ return default
105+
106+
84107
85108def main ():
86109 # Try to find out which list is being administered
@@ -1763,8 +1786,7 @@ def clean_input(x):
17631786 errors = []
17641787 removes = []
17651788 for user in users :
1766- quser = urllib .parse .quote (user )
1767- if '%s_unsub' % quser in cgidata :
1789+ if _member_field_in_cgidata (cgidata , user , 'unsub' ):
17681790 try :
17691791 _ = D_
17701792 whence = _ ('member mgt page' )
@@ -1778,7 +1800,7 @@ def clean_input(x):
17781800 doc .addError (_ (f'Ignoring changes to deleted member: { user } ' ),
17791801 tag = _ ('Warning: ' ))
17801802 continue
1781- value = '%s_digest' % quser in cgidata
1803+ value = _member_field_in_cgidata ( cgidata , user , 'digest' )
17821804 try :
17831805 mlist .setMemberOption (user , mm_cfg .Digests , value )
17841806 except (Errors .AlreadyReceivingDigests ,
@@ -1788,28 +1810,28 @@ def clean_input(x):
17881810 # BAW: Hmm...
17891811 pass
17901812
1791- newname = cgidata . getfirst ( quser + '_realname ' , '' )
1813+ newname = _member_field_getfirst ( cgidata , user , 'realname ' , '' )
17921814 newname = Utils .canonstr (newname , mlist .preferred_language )
17931815 mlist .setMemberName (user , newname )
17941816
1795- newlang = cgidata . getfirst ( quser + '_language ' )
1817+ newlang = _member_field_getfirst ( cgidata , user , 'language ' )
17961818 oldlang = mlist .getMemberLanguage (user )
17971819 if Utils .IsLanguage (newlang ) and newlang != oldlang :
17981820 mlist .setMemberLanguage (user , newlang )
17991821
1800- moderate = not not cgidata . getfirst ( quser + '_mod ' )
1822+ moderate = not not _member_field_getfirst ( cgidata , user , 'mod ' )
18011823 mlist .setMemberOption (user , mm_cfg .Moderate , moderate )
18021824
18031825 # Set the `nomail' flag, but only if the user isn't already
18041826 # disabled (otherwise we might change BYUSER into BYADMIN).
1805- if '%s_nomail' % quser in cgidata :
1827+ if _member_field_in_cgidata ( cgidata , user , 'nomail' ) :
18061828 if mlist .getDeliveryStatus (user ) == MemberAdaptor .ENABLED :
18071829 mlist .setDeliveryStatus (user , MemberAdaptor .BYADMIN )
18081830 else :
18091831 mlist .setDeliveryStatus (user , MemberAdaptor .ENABLED )
18101832 for opt in ('hide' , 'ack' , 'notmetoo' , 'nodupes' , 'plain' ):
18111833 opt_code = mm_cfg .OPTINFO [opt ]
1812- if '%s_%s' % ( quser , opt ) in cgidata :
1834+ if _member_field_in_cgidata ( cgidata , user , opt ):
18131835 mlist .setMemberOption (user , opt_code , 1 )
18141836 else :
18151837 mlist .setMemberOption (user , opt_code , 0 )
0 commit comments