Main  /  Edit  /  History  /   /  Users Area

Working With Forms

Create a Form

First we create our simple form. Let's create content.h file and add header:

#include <cppcms/view.h>
#include <cppcms/form.h>

Then create a form class derived from cppcms::form:

namespace content  {
struct info_form : public cppcms::form {

Then we add widgets to this form:

cppcms::widgets::text name;
cppcms::widgets::radio sex;
cppcms::widgets::select marital;
cppcms::widgets::numeric<double> age;
cppcms::widgets::submit submit;

Where, text is a text input field, radio is a multiple choice field, select is a drop down list of choices, number<> is a number of specific type and submit is a submit button.

Now we create a constructor for our class:

info_form()
{

Then we setup an information messages for the form widgets:

name.message("Your Name");
sex.message("Sex");
marital.message("Marital Status");
age.message("Your Age");
submit.value("Send");

Then we register all the widgets withing the form. This allows centralized rendering, loading and validation of the entire form.

add(name);
add(sex);
add(marital);
add(age);
add(submit);

Note, cppcms::form::add only registers the object to the form. It does not transfer ownership on the widget.

Now lets setup some values for our selection widgets

sex.add("Male","male");
sex.add("Female","female");
marital.add("Single","single");
marital.add("Married","married");
marital.add("Divorced","divorced");

Note: the first parameter is the text that will be displayed, and the second one is a special key that defines our choice.

Now, let's define some basic restrictions on the fields:

name.non_empty();
age.range(0,120);

We make sure that the name is filled and the age is in expected range. That's it for our constructor.

And now we can add it to our content class (with some other fields for future use).

struct message : public cppcms::base_content {
    std::string name,state,sex;
    double age;
    info_form info;
};

Form in templates

First we create our output:

<% if not empty name %>
        <h1>Hello <%= name %></h1>
        <p>You are <%= sex %>, <%= state %></p>
        <p>Your age is <%= age %></p>
<% else %>
    <h1>Input your details</h1>
<% end %>

Then we put our form using tag <% form as_p info %>:

<form method="post" action="" >
<% form as_p info %>
</form>

The flag as_p tells to render form info using paragraphs.

<a name="Working-with-form-in-code:"></a>

Working with form in code:

First we create our content that contains required form.

content::message c;

Then we test, if something was send:

if(request().request_method()=="POST") {

If so we load our form and validate it:

    c.info.load(context());
    if(c.info.validate()) {

if the form is valid, we can do anything we want. For example setup our content fields with appropriate values from the form.

        c.name=c.info.name.value();
        c.sex=c.info.sex.selected_id();
        c.state=c.info.marital.selected_id();
        c.age=c.info.age.value();

We clear it at the end, because we want user to put new values

        c.info.clear();

Now we can render our template as usual:

    }
}
render("message",c);

Additional Validation

Let's assume that standard widgets checks are not good enough. We can extend our validation manually.

We can add out own restrictions by overriding cppcms::form::validate member function by adding the following code to content::info_form

virtual bool validate()
{
    if(!form::validate()) 
        return false;
    if(marital.selected_id()!="single" 
       && age.value()<18)
    {
        marital.valid(false);
        return false;
    }
    return true;
}

First of all we need to check that basic form validation is performed by calling form::validate then we add our own restrictions like for example, martial status can be only single for non-adult.

When we detect such situation we mark our widget as invalid and return false for entire validation process.

<a name="Security-Considerations:-Cross-Site-Request-Forgery"></a>

Security Considerations: Cross Site Request Forgery

The straight forward approach to the forms is vulnerable to Cross Site Request Forgery an authorized person is tricked to perform an action that he was not expected to do (follow the link for more detail).

In order prevent CSRF every POST form should include a special hidden field that holds a session specific CSRF token.

So we need to add a small code <% csrf %> streight after <form ...> field to our template:

<form method="post" action="" ><% csrf %>
<% form as_p info %>
</form>

And enable csrf checks in the configuration file:

"security" : {
   "csrf" : {
      "enable" : true
   }
}

The <% csrf %> command would generate a special hidden input field that inject session specific token and handle all tests for you.

In case of detection of CSRF attack the cppcms::form::load would throw a cppcms::request_forgery_error exception

That would be caught and reported to the logs at higher levels.

Note: CSRF token should be used with POST fields only and never GET request method.


Views Inheritance | Top | Sessions

About

CppCMS is a web development framework for performance demanding applications.

Support This Project

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Navigation

Main Page



Valid CSS | Valid XHTML 1.0