» A Great Article Series on Agavi
Vikram Vaswani has written a great article series on Agavi. The five-part series starts off with the basic but in the end goes quite deep into building a multi presentational layer web application. Go read it on the IBM developerWorks! Now!
- Part 1: Open a whole new world with Agavi
- Part 2: Add forms and database support with Agavi and Doctrine
- Part 3: Add authentication and administrative functions with Agavi
- Part 4: Create an Agavi search engine with multiple output types including XML, RSS, or SOAP
- Part 5: Add paging, file uploads, and custom input validators to your Agavi application
» Agavi 1.0.0 Beta 8 Includes a Critical Security Fix
Agavi 1.0.0 Beta 8 Includes a Critical Security Fix
A new Agavi 1.0.0 Beta 8 was released late yesterday (European time). As usual, the new version contains several improvements and bug fixes but also a fix to a critical cross-site scripting vulnerability described in http://trac.agavi.org/ticket/1019. The vulnerability actually affects, as far as we know, only Internet Explorer 6 and 7 which fail to encode URL according to standards.
Affected versions:
- Agavi 0.11 up to and including 0.11.6-RC2
- Agavi 1.0 up to and including 1.0.0-beta7
Solutions
- Upgrade to 0.11.6 or 1.0.0 Beta 8
- Patch your Agavi with a hot fix attached to the ticket
- Use one of the workarounds described in the ticket.
» Agavi Tip: Automatic Output of Validation Errors
Agavi Tip: Automatic Output of Validation Errors
I decided today to stop printing my validation error messages manually in the template. I knew that Form Population Filter (one of Agavi’s many excellent features also referred to as FPF) could be used to inject error messages into the HTML form next to erroneous fields but I want my error messages above the form. Once again David was there to help me and with a few iterations of trial and error he offered a working solution for me. And the solution was so simple and nice that I just had to blog it.
Filter Configuration
global_filters.xml
<filter name="FormPopulationFilter" class="AgaviFormPopulationFilter">
<ae:parameter name="methods">
<ae:parameter>write</ae:parameter>
</ae:parameter>
<ae:parameter name="output_types">
<ae:parameter>html</ae:parameter>
</ae:parameter>
<ae:parameter name="error_messages">
<ae:parameter name="self::${htmlnsPrefix}form">
<ae:parameter name="location">before</ae:parameter>
<ae:parameter name="container"><![CDATA[<div class="errors">${errorMessages}</div>]]></ae:parameter>
<ae:parameter name="markup"><![CDATA[<p class="error">${errorMessage}</p>]]></ae:parameter>
</ae:parameter>
</ae:parameter>
</filter>
And that’s it. FPF injects all error messages above your form. Each error message in its own paragraph and all paragraphs wrapped inside a <div>
Want More?
FPF can have different rules for different kinds of errors and with XPath you can inject them pretty much anywhere you want. See the Agavi’s sample application for more examples.
» Agavi 1.0.0 beta 7 released!
Agavi 1.0.0 Beta 7
Out of many changes there are two (or actually three) I want to emphasise because they may be backwards compatibility breaks for someone.
Default View Security Fixes
Two separate changes have been made to action’s default view handling to ensure strict security.
To make sure a developer doesn’t use unvalidated input data by mistake global unvalidated request data is locked during action and view execution. However, before 1.0.0 beta 7 it was possible to access the global request data in Action::getDefaultViewName(). This has now been fixed and anyone using the global request will be punished severely with an exception. Mind you, it has always been recommended that no application logic is put into getDefaultView(). It should just return the default view name for the action.
It was also recently discovered that the strict validation mode (default mode in Agavi 1.0) wasn’t working as it is supposed to when an action didn’t provide an execute method for the current request and the default view was used. In this case the request data was given to the view unfiltered which is against the strict validation mode principles.
PHP 5.2.8 Requirement (conditional)
Due to issues with magic quotes in PHP’s earlier versions and the fact that making Agavi bullet proof in all situations is beginning to be a maintenance nightmare it was decided to require PHP 5.2.8 if magic_quotes_gpc is ON. I’ll repeat: Agavi requires PHP 5.2.8 ONLY if magic_quotes_gpc is enabled on your server. If it’s not you can still use Agavi with PHP 5.2.0 or later (5.1.3 with Agavi 0.11).
» Agavi Tip: Validation Gotchas
Agavi Validation Gotchas
Agavi’s input validation system is extremely versatile and even people with long history with Agavi - me for example - sometimes struggle to get their head around it. So I decided to put down a few gotchas. Here goes…
Validators Can Be Grouped
You can use AgaviAndValidator, AgaviOrValidator and AgaviXorValidator to group several validators.
<validator class="or">
<validators>
<validator class="email" required="false" >
<arguments>
<argument>email</argument>
</arguments>
</validator>
<validator class="MyPhoneNumberValidator" required="false" >
<arguments>
<argument>phone</argument>
</arguments>
</validator>
</validators>
<errors>
<error>Please provide email or phone</error>
</errors>
</validator>
Validator Can Depend on Another Validator
Quite often you only want validate input B only if the user provided input A. Agavi makes this simple:
<validator ... required="false" provides="street_set">
<arguments base="contact">
<argument>Street</argument>
</arguments>
</validator>
<validator ... required="true" depends="contact[street_set]">
<arguments base="contact">
<argument>Zip</argument>
</arguments>
</validator>
Note: argument’s
baseattribute affects also provides/depends attributes (see example above) !!
Pimp My Error Messages
A validator can throw different error message based on what went wrong and error messages can be translated on the fly. Error message options vary between validators. See API docs for more.
<validator class="string" translation_domain="default.errors">
<arguments>
<argument>my_input</argument>
</arguments>
<errors>
<error for="required">Please fill this input</error>
<error for="max">Please keep it shorter than 40 characters</error>
</errors>
<ae:parameters>
<ae:parameter name="max">40</ae:parameter>
</ae:parameters>
</validator>
Validating Array Inputs
<input name=”rows[Id]”
<arguments base="rows">
<argument>Id</argument>
</arguments>
<!-- or -->
<arguments>
<argument>rows[Id]</argument>
</arguments>
<input name=”rows[1][Id]”
<arguments base="rows[]">
<argument>Id</argument>
</arguments>
<input name=”rows[]”
<arguments base="rows[]">
<argument/>
</argument>
Validator Can Normalize And Export Combined Values
This example shows how to get AgaviDateValidator to validate a compound value. But that’s not all! It’ll even export a proper timestamp for you to use in your application code.
<validator class="AgaviDateTimeValidator">
<arguments>
<argument name="AgaviDateDefinitions::DATE">day</argument>
<argument name="AgaviDateDefinitions::MONTH">month</argument>
<argument name="AgaviDateDefinitions::YEAR">year</argument>
</arguments>
<errors>
<error>Validation error</error>
</errors>
<ae:parameters>
<ae:parameter name="export">MyDatestamp</ae:parameter>
</ae:parameters>
</validator>
Remember to Validate ALL Input
Validation is not limited to GET/POST input parameters but HTTP headers and cookies can (and should) be validated too. Use the source attribute to tell the validator where to get the data from.
<validator ... source="headers"> <argument>REFERER</argument>
Validator is ran only if the parameter is non-empty.
By default the validator base class AgaviValidator checks that all the arguments are set before executing the actual validation. If the input value is empty or non-existent but required error is thrown. But if required attribute is set to False the validation just quietly continues to another validator. Normally this is not a problem but you might want to code a custom validator that exports a default value for empty parameters. In this case you need to override AgaviValidator’s checkAllArgumentsSet().
Did I forget something?
Join #agavi IRC channel and hassle me there or send email to veikko@veikko.fi.
» Agavi Tip: Checking Validation Results
Agavi Tip: Checking Validation Results
Normally when an input validator fails you’ll just want to show the form again and let FormPopulationFilter do its magic (you do know you can it have re-populate the form and inject error messages into the form, don’t you?-). But occasionally you want to decide the next move based on what validator failed. With Agavi 1.0 getting validation incidents of a named validator is this simple:
public function handleError(AgaviRequestDataHolder $rd)
{
$vm = $this->container->getValidationManager();
if (count($vm->getReport()->getValidatorResult('my_special_validator')->getIncidents())) {
return 'CriticalError';
}
else {
return 'Error';
}
}
Note: that AgaviValidationValidatorResult was missing from the core autoload.xml in 1.0 Beta 6. This has been fixed in the SVN If you aren’t using the bleeding edge version add the following line to your
config/autoload.xml.
<autoload name="AgaviValidationValidatorResult">%core.agavi_dir%/validator/AgaviValidationValidatorResult.class.php</autoload>
Agavi Debug Tools now supports Propel query logging (both FirePHP and HTML output). Just configure Propel to use DebugPDO and AdtFilter to use AdtPropelDataSource. Nothing else required.
» Agavi 1.0.0 Beta 6
Agavi 1.0.0 Beta 6 - Even More Secure
Default: Strict Validation ALWAYS
Agavi has a very special input validation system which, by default, will not let your application use any unvalidated input data. And this doesn’t mean only POST or GET parameters in HTTP world but also cookies and headers. Remember, those too are user input and must be considered insecure.
This strict validation mode has been the default setting for production environment for quite some time already but after Agavi was blamed for somebody’s poor input validation it was made default for development environments too. It had already been discussed earlier because different defaults for different environments was sometimes confusing and caused applications to break when moved to production.
Production-ready Exception Templates
Because people seem to be too lazy to configure exception templates for production use a new set of default templates was added to Agavi 1.0.0 Beta 6.
Download Agavi: http://www.agavi.org/download
Thanks to Harald “digitarald” Kirschner ADT’s FirePHP output is now 174% nicer. And a few bugs was fixed too. Check out ADT at http://adt.projectbin.org/.
» ADT Agavi Debug Tools
I’ve released a first public version of a debug toolbar for Agavi. It supports traditional HTML output but you can also use it with FirePHP - extremely helpful when developing AJAX stuff with Agavi. Check it out at http://adt.projectbin.org/.
