Hidden form fields not accepted by form.accept()?

36 views
Skip to first unread message

Ruiwen Chua

unread,
Oct 25, 2010, 12:27:50 AM10/25/10
to web2py-users
Hi all,

I have created a manual HTML form (not FORM() or SQLFORM()) that has a
few hidden fields (ie. <input type="hidden">..)

When this form posts back to the controller, form.accepts() returns
True, but only the non-hidden field (there is only one, the rest are
hidden) is saved to the database. The other fields all get saved as
NULL.

Is there something I'm missing?

Thanks

mdipierro

unread,
Oct 25, 2010, 12:30:29 AM10/25/10
to web2py-users
if you use

form.accepts()

what is form if you do not use FORM or SQLFORM?

Ruiwen Chua

unread,
Oct 25, 2010, 12:39:39 AM10/25/10
to web2py-users
Apologies, I wasn't clear. I meant that the form in the view is static
HTML and not generated by SQLFORM.

However, in the action that receives the POST, I instantiate a new
SQLFORM for that model and pass request.post_vars to it.

mdipierro

unread,
Oct 25, 2010, 12:43:48 AM10/25/10
to web2py-users
The hidden fields will be in request.vars but not in form.vars because
accepts does not know they are supposed to be there and protects you
from injection attacks.

You can also try use this:

form=SQLFORM(....,hidden=dict(key='value'))

Massimo

Ruiwen Chua

unread,
Oct 25, 2010, 12:46:30 AM10/25/10
to web2py-users
Yes, the hidden input values do seem to appear in request.post_vars.

I call form.accepts(), like so: form.accepts(request.post_vars,
formname=None)

And even so, only the non-hidden field is saved to the database.

mdipierro

unread,
Oct 25, 2010, 1:03:51 AM10/25/10
to web2py-users
I understand. That is intended. That is a security mechanism.
You must use SQLFORM(...,hidden=...)

Ruiwen Chua

unread,
Oct 25, 2010, 1:07:24 AM10/25/10
to web2py-users
Thanks for the clarification.

Though, in what way is this a security mechanism?

mdipierro

unread,
Oct 25, 2010, 1:15:16 AM10/25/10
to web2py-users
Say you have:


db.define_table('user',Field('name'),Field('manager',writable=False,default='no')

and a registration form:

def register():
form=SQLFORM(db.user)
form.accepts(request.vars)

If attackers were allowed to do

http://.../register?name=me&manager=yes

they would be able to change the manager status even if it does not
appears in the form. Only fields that are declared as writable and
visible to SQLFORM can be inserted in the db.

web2py has lots of security mechanisms and we are working on even
more!

Massimo

Ruiwen Chua

unread,
Oct 25, 2010, 2:17:52 AM10/25/10
to web2py-users
I see. So form.accept() will not parse any field unless explicitly
defined in SQLFORM?

(Ok I'm not sure if I should start another thread for this, but a few
issues I found with using SQLFORM.. so perhaps I'm still doing
something wrong.)

a) I have multiple forms (for the same model) on a page, now generated
using SQLFORM

However, each generated SQLFORM gives identical id attributes in the
<div>s it generates, and that breaks validation

b) I need these forms to post to a different controller from the one
that generated them (via normal post or AJAX)

What's the best way to get the receiving controller to recognise the
incoming form with the hidden fields, seeing as it was generated in a
different controller?


Thanks for the help so far though.

On Oct 25, 1:15 pm, mdipierro <mdipie...@cs.depaul.edu> wrote:
> Say you have:
>
> db.define_table('user',Field('name'),Field('manager',writable=False,default ='no')

mdipierro

unread,
Oct 25, 2010, 7:54:55 AM10/25/10
to web2py-users


On Oct 25, 1:17 am, Ruiwen Chua <rwc...@gmail.com> wrote:
> I see. So form.accept() will not parse any field unless explicitly
> defined in SQLFORM?
>
> (Ok I'm not sure if I should start another thread for this, but a few
> issues I found with using SQLFORM.. so perhaps I'm still doing
> something wrong.)
>
> a) I have multiple forms (for the same model) on a page, now generated
> using SQLFORM
>
> However, each generated SQLFORM gives identical id attributes in the
> <div>s it generates, and that breaks validation

http://www.web2py.com/book/default/chapter/07#Multiple-forms-per-page

> b) I need these forms to post to a different controller from the one
> that generated them (via normal post or AJAX)
>
> What's the best way to get the receiving controller to recognise the
> incoming form with the hidden fields, seeing as it was generated in a
> different controller?

If you have the form object:
accpets(request.post_vars,None,formname=None)
If you do not just use request.vars and do an db io manually.
Using a different controller function breaks validation.

Ruiwen Chua

unread,
Oct 26, 2010, 12:09:08 AM10/26/10
to web2py-users


On Oct 25, 7:54 pm, mdipierro <mdipie...@cs.depaul.edu> wrote:
> On Oct 25, 1:17 am, Ruiwen Chua <rwc...@gmail.com> wrote:
>
> > I see. So form.accept() will not parse any field unless explicitly
> > defined in SQLFORM?
>
> > (Ok I'm not sure if I should start another thread for this, but a few
> > issues I found with using SQLFORM.. so perhaps I'm still doing
> > something wrong.)
>
> > a) I have multiple forms (for the same model) on a page, now generated
> > using SQLFORM
>
> > However, each generated SQLFORM gives identical id attributes in the
> > <div>s it generates, and that breaks validation
>
> http://www.web2py.com/book/default/chapter/07#Multiple-forms-per-page
>

Thanks for the pointer. I just tried the example on that page and got:

in the_view.html

<div id="example">
<form action="" enctype="multipart/form-data" method="post">
<div id="answer_response__row">
<!-- snip -->
</div>

<div id="submit_record__row">
<!-- snip -->
</div>

<div class="hidden">
<input name="_formname" type="hidden" value="form_one" />
</div>
</form>

<form action="" enctype="multipart/form-data" method="post">
<div id="answer_response__row">
<!-- snip -->
</div>

<div id="submit_record__row">
<!-- snip -->
</div>

<div class="hidden">
<input name="_formname" type="hidden" value="form_two" />
</div>
</form>
</div>


and in thecontroller.py

f1 = SQLFORM(db.answer, formstyle='divs')
f2 = SQLFORM(db.answer, formstyle='divs')

if f1.accepts(request.vars, formname='form_one'):
response.flash = 'form one accepted'
if f2.accepts(request.vars, formname='form_two'):
response.flash = 'form two accepted'


The issue with duplicate HTML id attributes I'm referring to is such:

Note that "<div id="answer_response__row">" and " <div
id="submit_record__row">" both appear twice, once for each form.

As far as I know, HTML id attributes shouldn't repeat in the same HTML
document. So I'm not too sure if this behaviour is intentional?



> > b) I need these forms to post to a different controller from the one
> > that generated them (via normal post or AJAX)
>
> > What's the best way to get the receiving controller to recognise the
> > incoming form with the hidden fields, seeing as it was generated in a
> > different controller?
>
> If you have the form object:
> accpets(request.post_vars,None,formname=None)
> If you do not just use request.vars and do an db io manually.
> Using a different controller function breaks validation.

Unfortunately, I don't have the original form object, since it was
generated in another controller, say A, while I'm posting to
controller B.

I got around this issue by instantiating a new SQLFORM in the
receiving controller, then calling form.accepts(...) on it.

Seems to work that way.
Reply all
Reply to author
Forward
0 new messages