Skip to content

Commit e4a0b23

Browse files
author
Richard Jones
committed
. All forms now have "double-submit" protection...
...when Javascript is enabled on the client-side.
1 parent 5a983ba commit e4a0b23

File tree

3 files changed

+38
-11
lines changed

3 files changed

+38
-11
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Fixed:
1111
. mailgw checks encoding on first part too.
1212
. #511586 ] unittest FAIL: testReldate_date
1313
. Added a uniquely Roundup header to email, "X-Roundup-Name"
14+
. All forms now have "double-submit" protection when Javascript is enabled
15+
on the client-side.
1416

1517

1618
2002-01-24 - 0.4.0

roundup/cgi_client.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: cgi_client.py,v 1.100 2002-01-16 07:02:57 richard Exp $
18+
# $Id: cgi_client.py,v 1.101 2002-02-14 23:39:18 richard Exp $
1919

2020
__doc__ = """
2121
WWW request handler (also used in the stand-alone server).
@@ -80,6 +80,20 @@ def header(self, headers={'Content-Type':'text/html'}):
8080
if self.debug:
8181
self.headers_sent = headers
8282

83+
single_submit_script = '''
84+
<script language="javascript">
85+
submitted = false;
86+
function submit_once() {
87+
if (submitted) {
88+
alert("Your request is being processed.\\nPlease be patient.");
89+
return 0;
90+
}
91+
submitted = true;
92+
return 1;
93+
}
94+
</script>
95+
'''
96+
8397
def pagehead(self, title, message=None):
8498
url = self.env['SCRIPT_NAME'] + '/'
8599
machine = self.env['SERVER_NAME']
@@ -113,10 +127,12 @@ def pagehead(self, title, message=None):
113127
''')
114128
else:
115129
add_links = ''
130+
single_submit_script = self.single_submit_script
116131
self.write(_('''<html><head>
117132
<title>%(title)s</title>
118133
<style type="text/css">%(style)s</style>
119134
</head>
135+
%(single_submit_script)s
120136
<body bgcolor=#ffffff>
121137
%(message)s
122138
<table width=100%% border=0 cellspacing=0 cellpadding=2>
@@ -348,9 +364,9 @@ def _add_assignedto_to_nosy(self, props):
348364
if self.nodeid:
349365
cl = self.db.classes[self.classname]
350366
l = cl.get(self.nodeid, 'nosy')
351-
if assignedto_id in l:
352-
return
353-
props['nosy'] = l
367+
if assignedto_id in l:
368+
return
369+
props['nosy'] = l
354370
else:
355371
props['nosy'] = []
356372
if assignedto_id not in props['nosy']:
@@ -746,7 +762,7 @@ def login(self, message=None, newuser_form=None, action='index'):
746762
self.write(_('''
747763
<table>
748764
<tr><td colspan=2 class="strong-header">Existing User Login</td></tr>
749-
<form action="login_action" method=POST>
765+
<form onSubmit="return submit_once()" action="login_action" method=POST>
750766
<input type="hidden" name="__destination_url" value="%(action)s">
751767
<tr><td align=right>Login name: </td>
752768
<td><input name="__login_name"></td></tr>
@@ -770,7 +786,7 @@ def login(self, message=None, newuser_form=None, action='index'):
770786
<p>
771787
<tr><td colspan=2 class="strong-header">New User Registration</td></tr>
772788
<tr><td colspan=2><em>marked items</em> are optional...</td></tr>
773-
<form action="newuser_action" method=POST>
789+
<form onSubmit="return submit_once()" action="newuser_action" method=POST>
774790
<input type="hidden" name="__destination_url" value="%(action)s">
775791
<tr><td align=right><em>Name: </em></td>
776792
<td><input name="realname" value="%(realname)s"></td></tr>
@@ -1079,10 +1095,12 @@ def pagehead(self, title, message=None):
10791095
''')
10801096
else:
10811097
add_links = ''
1098+
single_submit_script = self.single_submit_script
10821099
self.write(_('''<html><head>
10831100
<title>%(title)s</title>
10841101
<style type="text/css">%(style)s</style>
10851102
</head>
1103+
%(single_submit_script)s
10861104
<body bgcolor=#ffffff>
10871105
%(message)s
10881106
<table width=100%% border=0 cellspacing=0 cellpadding=2>
@@ -1182,6 +1200,10 @@ def parsePropsFromForm(db, cl, form, nodeid=0):
11821200

11831201
#
11841202
# $Log: not supported by cvs2svn $
1203+
# Revision 1.100 2002/01/16 07:02:57 richard
1204+
# . lots of date/interval related changes:
1205+
# - more relaxed date format for input
1206+
#
11851207
# Revision 1.99 2002/01/16 03:02:42 richard
11861208
# #503793 ] changing assignedto resets nosy list
11871209
#

roundup/htmltemplate.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: htmltemplate.py,v 1.71 2002-01-23 06:15:24 richard Exp $
18+
# $Id: htmltemplate.py,v 1.72 2002-02-14 23:39:18 richard Exp $
1919

2020
__doc__ = """
2121
Template engine.
@@ -708,7 +708,7 @@ def render(self, filterspec={}, filter=[], columns=[], sort=[], group=[],
708708
# display the filter section
709709
if (show_display_form and
710710
self.instance.FILTER_POSITION in ('top and bottom', 'top')):
711-
w('<form action="%s">\n'%self.classname)
711+
w('<form onSubmit="return submit_once()" action="%s">\n'%self.classname)
712712
self.filter_section(filter_template, filter, columns, group,
713713
all_filters, all_columns, show_customization)
714714
# make sure that the sorting doesn't get lost either
@@ -790,7 +790,7 @@ def render(self, filterspec={}, filter=[], columns=[], sort=[], group=[],
790790
# display the filter section
791791
if (show_display_form and hasattr(self.instance, 'FILTER_POSITION') and
792792
self.instance.FILTER_POSITION in ('top and bottom', 'bottom')):
793-
w('<form action="%s">\n'%self.classname)
793+
w('<form onSubmit="return submit_once()" action="%s">\n'%self.classname)
794794
self.filter_section(filter_template, filter, columns, group,
795795
all_filters, all_columns, show_customization)
796796
# make sure that the sorting doesn't get lost either
@@ -1000,7 +1000,7 @@ def render(self, nodeid):
10001000
# designators...
10011001

10021002
w = self.client.write
1003-
w('<form action="%s%s" method="POST" enctype="multipart/form-data">'%(
1003+
w('<form onSubmit="return submit_once()" action="%s%s" method="POST" enctype="multipart/form-data">'%(
10041004
self.classname, nodeid))
10051005
s = open(os.path.join(self.templates, self.classname+'.item')).read()
10061006
replace = ItemTemplateReplace(self.globals, locals(), self.cl, nodeid)
@@ -1030,7 +1030,7 @@ def render(self, form):
10301030
s = open(os.path.join(self.templates, c+'.newitem')).read()
10311031
except IOError:
10321032
s = open(os.path.join(self.templates, c+'.item')).read()
1033-
w('<form action="new%s" method="POST" enctype="multipart/form-data">'%c)
1033+
w('<form onSubmit="return submit_once()" action="new%s" method="POST" enctype="multipart/form-data">'%c)
10341034
for key in form.keys():
10351035
if key[0] == ':':
10361036
value = form[key].value
@@ -1043,6 +1043,9 @@ def render(self, form):
10431043

10441044
#
10451045
# $Log: not supported by cvs2svn $
1046+
# Revision 1.71 2002/01/23 06:15:24 richard
1047+
# real (non-string, duh) sorting of lists by node id
1048+
#
10461049
# Revision 1.70 2002/01/23 05:47:57 richard
10471050
# more HTML template cleanup and unit tests
10481051
#

0 commit comments

Comments
 (0)