Month: July 2007

Solar Form Validation Types

This is partially for my reference and partially for anyone looking at validating in their Solar_Form forms – here’s the validation methods (as defined in /Solar/Filter.php):

Each of these can be used when defining the form, commonly in the setElements structure like so:

[php]
$form = Solar::factory(‘Solar_Form’);
$form->setElements(array(
‘password’=>array(
‘type’=>’password’,
‘label’=>’password’,
‘require’=>true,
‘valid’=>array(
array(‘notBlank’,’Enter a password!’)
)
)
));
[/php]

#reftable { border-collapse: collapse; }
#reftable td { padding: 3px; border: 1px solid #C0D0D9 }
#reftable td.header { background-color: #C0D0D9 }

Type Details
alnum Validate that valid is only alphabetic and numeric characters
alpha Validate that value is only alphabetic
blank Validate that there’s nothing in the field, it’s blank
callback Validate against a callback function – call is given the value and callback function name
ctype Checks the value with the ctype_* function built into PHP
email Validates as a valid email address
feedback Validates and only returns a message on failure, returns feedback as a string
inKeys Validate that the value is one of the keys of the given array
inList Validates that the entered value is in a given array (as value, not key)
integer Checks to ensure that the value is an integer (contains + or – and numbers, no decimals)
ipv4 Validates to check for a correct ipv4 address
isoDate Ensures that value is a correctly formatted ISO 8601 date (yyyy-mm-dd)
isoTime Validates that value is a correct ISO 8601 time format (HH:MM:SS)
isoTimestamp Validates that value matches the full ISO 8601 timestamp format (yyyy-mm-ddThh:ii:ss)
localeCode Checks to see if the value is a valid locale code (two a-z letters, an underscore and two A-Z letters)
max Checks to see if the given value is greater than or equal to the ‘max’ given
maxLength Checks the value to ensure that it’s less than or equal to the maximum length given
mimeType Checks to see if the value is a valid mime type (follows the regular expression: [a-zA-Z][-.a-zA-Z0-9+]*)
min Checks to see if the value given is less than or equal to a minimum
minLength Checks the value to be sure it’s at least a minimum length
multiple Allows you to perform multiple validations on the same value
notZero Ensures that the value does not exactly equal zero
notBlank Ensure that a string, when trimmed, is not empty
range Ensure that the value given is in a certain range
rangeLength Validate that the length of the given value is within a certain range
regex Match the value against a given regular expression
scope Checks to be sure that the given value only has a certain number of digits and decimals
sepWords Validate that the value is made up of separate words
uri Validate that the input is a valid URI
word Ensure that the value is made up of only “word” characters

Some Solar Form Fun

So, after getting started with the Solar framework, I figured that I’d keep going and try to really work up an application with it and get familiar with the framework. A next obvious step (well, to me it’s obvious) is to dive into using the form functionality that comes with it. I started small, but eventually worked into a standard part of just about any application these days.

Like learning anything, there were some growing pains as I figured out how to work with it (many thanks to the guys in #solarphp on Freenode) and how to get the following code up and working. The Solar_Auth component makes it simple to drop on top of whatever kind of authentication system (LDAP, ini files, htpasswd) but the method I chose is one of the most common I’ve seen – authentication from a database table. The Solar_Auth_Adapter_Sql handles most of the work and makes defining the table a snap.

Let’s start with the entire code for the controller, User.php:

[php]

class MySite_App_User extends MySite_App_Base {

protected $_layout = ‘default’;
protected $_action_default = ‘index’;
protected $_view=”;

public function actionIndex(){ }
public function actionLogin(){

$sql=Solar::factory(‘Solar_Sql’);
$config=array(
‘adapter’=>’Solar_Auth_Adapter_Sql’,
‘config’=>array(
‘sql’ =>$sql,
‘table’ =>’users’,
‘handle_col’=>’username’,
‘passwd_col’=>’password’,
‘uid_col’ =>’ID’,
‘process_login’=>’submit login’
)
);
$auth = Solar::factory(‘Solar_Auth’,$config);
$auth->start();

$form = Solar::factory(‘Solar_Form’);
$form->setElements(array(
‘handle’=>array(
‘type’=>’text’,
‘label’=>’username:’,
‘require’=>true,
‘valid’=>array(
array(‘notBlank’,’Please enter a username!’)
)
),
‘passwd’=>array(
‘type’=>’password’,
‘label’=>’password:’,
‘require’=>true,
‘valid’=>array(
array(‘notBlank’,’Please enter a password!’)
)
),
‘process’=>array(
‘type’=>’submit’,
‘value’=>’submit login’
)
));
$request = Solar::factory(‘Solar_Request’);
$process = $request->post(‘process’);
if($process==’submit login’){
$auth->processLogin();
$form->populate();
if($form->validate() && $auth->isValid()){
$this->output.=’logging in…’;
}else{
$this->output.=’Invalid login!’;
}
}
$form->feedback=NULL;
$this->forms[‘test_form’]=$form;
}
}

[/php]

Now, let’s go through this piece by piece and make it a bit more clear for the non-Solar using crowd (of which I used to belong to).

We’ve defined the controller’s class as extending the MySite_App_Base (see the previous article as to how this is for templating the site) and define some basic properties for the layout/template to use, the default action, and the view to use by default. Below that, there’s two other properties – forms and output. The second is just a general output value that’s used in the /User/View/login.php file as a message. The first, however, is a special container for our form. Later on, you’ll see where the Solar_Form instance is appended to this property and how it’s executed in the view.

Since we’re only really worried about the login form, it’s the only action that’s built out. The function starts by defining the configuration for the Solar_Auth object we’re going to create. The “adapter” setting tells it we want to use the SQL functionality and the “config” array gives the details. The only tricky parts about these values is in the process_login settings. This will need to correspond to the value of your submit button to make things work correctly.

The next two big parts of the action are the creation of the Solar_Auth object (with our $config options) and the Solar_Form object. The first is what handles all of the validation and authentication functionality and the second is the object around which we build our form. That’s what the setElements function is for…

The setElements function is flexible, but I used it to contain a series of arrays that each represent an element in the form. The keys are the element names – “handle”, “passwd” and “process” – and each is a subarray with several settings defined inside. Things like the type of element, the text to have before it (Solar_Form does a basic layout), if the field is required, and how to validate it. On both the username (handle) and password (passwd) fields, I added a simple notBlank with a message to ensure that there’s something in the field. The last item, “process”, is the simplest.

Now the real fun begins – we have our form defined and the $auth object made so we can validate the username and password that’s entered, now we just need to grab the results of the form’s submission and perform the check. We can do this by creating a Solar_Request instance with direct access to the HTTP request. The value we need to watch for on the submit (the value of the “process” form element) is pulled into the $process variable via a call to post() on the request object. The “if” statement then checks for the value of it and, if it’s set, tries to perform the validation.

The processLogin() method called on the $auth object is what does the work here. It runs the check and then, if everything’s okay, sets the status property of the $auth object to “VALID”. The populate() function just repopulates the form’s values back into it (just in case it fails) and the validate() that’s called checked our form’s validation (like the notBlanks we added earlier). The isValid method called on the $auth object checks to see if the status property has been set to “VALID” indicating that the authentication was a success.

The next part is simple – if it’s a success, it outputs a success message and if not, tells the user that it was an “invalid login”. Right below the if statement is a handy little setting that I like because I want to control things in my form – the feedback setting. If set to false, it can silence the feedback that Solar automatically gives.

Remember how I said that the $forms property would come in handy later on? Well, the last part of this script is where it’s at. The Solar_Form object is appended to the $forms array, a value passed out into the view.

Speaking of the view, let’s see how this is all outputted:

[php]

echo $this->escape($this->output);
echo $this->form($this->forms[‘test_form’]);

[/php]

Is this a great framework or what? That’s all it takes to fire off the form in your View and the rest is handled behind the scenes in the controller. There was also someone mentioning the other day (in #solarphp on Freenode – I just can’t promote them enough!) that was talking about using the Solar_User class to do much of the same thing. I opted for Solar_Auth mainly because there were just more docs for it on the Solar website, making it easier to get into. Might have to try that one next though….

Google’s Lemon

Has anyone seen or heard much about Google’s Lemon?

Lemon is a black box tester, which assumes no knowledge of the internal structure of an application or device.

According to Google security team member Srinath Anantharaju, Lemon has been developed to detect cross-site scripting (XXS) vulnerabilties, but Google is “in the process of adding new attack vectors to improve the tool against [other] known security problems”.

Oh, and has anyone ever heard the term “fuzzers” before either?

Firefox 2.0.0.5 and httpOnly

Seems like a little something slipped under the radar in the latest release of everyone’s favorite browser (Firefox 2.0.0.5) – the introduction of httpOnly cookies. I know it’s not supported across the board, but it’s a step in the right direction.

As Alex mentions and includes a code snippet for, it’s as easy as setting a “httpOnly” parameter when creating the cookie to get it to work correctly.

What are httpOnly cookies? Well, the simple answer is that they protect your information in the cookie by making it inaccessible once they’ve been set so as to not allow other sites (or even the site that set it) to get at it. It can only be used when accessed by a HTTP request and *not* a script request.

Also, happily, PHP allows this to be set right along with the other parameters in setcookie as supported in PHP 5.2. No better time to upgrade, eh?

Starting Simply with Solar

In an effort to get to know as much of the technology out there, I wanted to branch out in my framework knowledge and try something I hadn’t looked much into yet – the Solar framework (PHP5). I’ve worked with both the Zend Framework and CakePHP on previous sites, so I wanted to see how they compared. The Solar framework, worked up by Paul Jones and team, provides much of the same functionality as the other two frameworks and is even based around the same structure – Model/View/Controller – to get the job done.

Since there’s no time like the present and no better way to learn how to use a tool than to just jump right in and get started, I looked up the great Getting Started section of the Solar manual to get on my way. It’s a great little section jam-packed with all the info that you’ll need to get started. I do want to, however, go back over my experience with it all as another example of how I set it up and got it working for my little application.

First of, obviously, you’ll need the latest version of the framework on your machine to get started. Unzip it in a place outside of the document root for where you’ll be building your application. This makes it easier if there’s others developers on the box that want to use it later on. Then, when you update the library, you don’t have to do it in ten different locations.

First off, you’ll need to set up your configuration file – you can put this just about anywhere really, but outside the document root is suggested since it could contain username/password information for your application. My document root is: /home/website_htdocs/sampleApp and my config file, Solar.config.php is located in /home/website_htdocs. Here’s the contents:

[php]
$config=array();

//Base action href
$config[‘Solar_Uri_Action’][‘path’]=’/’;

//Base public directory href
$config[‘Solar_Uri_Public’][‘path’]=’/public’;
$config[‘Solar_Controller_Front’][‘default’]=’index’;
$config[‘Solar_Controller_Front’][‘classes’]=array(
‘Solar_App’,
‘SampleApp_App’
);
$config[‘Solar_Sql’]=array(
‘adapter’ => ‘Solar_Sql_Adapter_Mysql’,
‘host’ => ‘localhost’,
‘user’ => ‘dbuser’,
‘pass’ => ‘dbpass’,
‘name’ => ‘sampleDB’
);

//Done!
return $config;
[/php]

The file is made up of the $config array with various values – among them the Solar_Uri_Action (the base action location) and the Solar_Uri_Public (the base for the public directory). That first option (Uri_Action) can be thought of the more “external” of the two. It tells the framework which URL the site will be using as a base. In my examples, I’m using mod_rewrite to handle the redirect of everything back down to the Front Controller (an index.php file that handles the routing), so I have it set to the root or “/”. Now, the Uri_Public setting is a little different story. This one is more “internal”, a setting that’s used to point the framework at the location of a public directory it can use to store things like CSS or Javascript files (and where anyone using Solar on the site) can use it too. I have it set to “/public” to point to a symlink that’s in my document root. Since Solar is installed to /home/website_htdocs/Solar, I made the link like this:

[php]
ln -s /home/website_htdocs/Solar/Solar/App/Public public
[/php]

This points a symlink of “public” to the Public directory over in the Solar installation. This is handy for working with shared files and provides us a location so we’re not polluting the views and all with unneeded code.

With the config file and symlink in place, the next step is the Front Controller. This is a PHP file that Solar uses to define a few more things and start up the framework to handle the requests coming in. Here’s what mine looks like:

[php]
set_include_path(‘/home/website_htdocs/Solar:/home/website_htdocs/SampleApp’);

require_once(‘Solar.php’);
Solar::start(‘/home/website_htdocs/Solar.config.php’);

$front=Solar::factory(‘Solar_Controller_Front’);
$front->display();

Solar::stop();
[/php]

There’s two main things set here – the include path (to define where our Solar and application directories are) and the start() call with the path to the config file created earlier.

You notice the “sampleApp” in the examples above – that’s the name of the example application I’ve worked up. It’s nothing special, but it does follow with the structure they suggest for using Solar. To contain all of the files, we’ll make a SampleApp directory in the document root of our site with a few files and directories under it:

App
  /Base
  /Base.php
  /Base/Helper
  /Base/Layout
  /Base/Locale
  /Base/Model
  /Base/View
  /Index
  /Index.php
  /Index/Helper
  /Index/Layout
  /Index/Locale
  /Index/Model
  /Index/View

I know that looks like a lot of stuff, but most of those directories won’t even be touched. We’re only really worried about a few things. First off, let’s look what this all means. Each of the controllers have a PHP file in the App directory. In our case, we have a Base.php and Index.php file for those two controllers. Base is a special example that allows for cross-controller file use and communication. So for our example, the only thing in here is:

[php]
class SampleApp_App_Base extends Solar_Controller_Page {
// nothing really needed here, unless you want
// shared methods and properties too
}
[/php]

This just makes the controller and extends the regular Solar controller. We’ll come back to the Base stuff in a second – for now, lets talk about the Index.php file:

[php]
Solar::loadClass(‘Solar_Controller_Page’);
class MySite_App_Index extends SampleApp_App_Base {

protected $_layout = ‘default’;
protected $_action_default = ‘index’;
protected $_view=”;
var $res;

public $output = ”;

function _setup(){
Solar::register(‘sql’, ‘Solar_Sql’);
}

public function actionIndex() {
$select=Solar::factory(‘Solar_Sql_Select’);
$select->from(‘test_tbl’,array(‘*’));
$res=$select->fetch(‘all’);
$this->res=$res;
$this->output = ‘this isdsds my example’;
}

}
[/php]

This is where the action happens in our little application. The best part of it all is that, way back in the configuration file (remember Solar.config.php?) we set up a default controller to run when one’s not specified – “index”. That means that, when people just hit the domain (like http://www.foo.com versus http://www.foo.com/pageName) they’ll get what’s in our Index controller.

So, what is in there? Well, lets look at the different parts. Our class extends the Base class instead of the normal Solar_Controller_Page so that we can use the things in the Base directories without any other special code. Because of this, we can use the layout defined in $_layout. Layouts allow for things like site templates without having to add the header/footer to each of the views for all of the controllers. The value, “default” corresponds to a PHP file, default.php, that’s located in /App/Base/Layout. Here’s what it contains:

[php]

imsothere.net
script(‘scripts/jquery/jquery.js’); ?>

layout_content;
?>

$(‘#mine’).append(‘

test

‘);

[/php]

This is pulled almost directly from their example with a few slight adjustments. One of the things that I wanted to do with my application was to use jQuery to handle some of the advanced Javascript. Because of this, I needed to include it in all of my pages. Naturally, in the layout is the perfect place. So I went to the jQuery site and grabbed the latest copy of their library. Now, remember that symlink we made a little while back – well, we’re going to go into that directory (you should see other directories inside it like scripts, images and styles) and inside of the scripts directory, make a jquery directory and put the file in there. That’ll match up with our example HTML, but you can always move it around to fit your needs. In our layout file above, you can see where it’s calling the script() function to grab that library and output an HTML tag for it.

The other missing piece to this puzzle is the view for the Index controller itself. The framework knows enough to apply the default template because of the value in $_layout, but it sill needs the value for layout_content to put in there. That’s why we need to make a view in /App/Index/View called index.php with the following content:

[php]
echo $this->escape($this->output);
echo “

"; print_r($this->res); echo "

“;
[/php]

You can match up the “output” and “res” properties from our actionIndex in the controller above. This is all packaged up and pushed into the layout and outputted. The script block at the bottom of the layout is just some Javascript using jQuery that adds a row to the table above it (I wanted a simple test to check if it was included and working correctly).

Finally, we get to the last piece of this mini application – the database connection. Now, you’ll remember way back in the config file, we defined some parameters:

[php]
$config[‘Solar_Sql’]=array(
‘adapter’ => ‘Solar_Sql_Adapter_Mysql’,
‘host’ => ‘localhost’,
‘user’ => ‘dbuser’,
‘pass’ => ‘dbpass’,
‘name’ => ‘sampleDB’
);
[/php]

Aren’t you glad that this isn’t in the document root? So, these set the different values your script will need to access your database – in this case, a local MySQL one. Setting all of this up here frees you up to only have to work with the objects in your controller:

[php]
$select=Solar::factory(‘Solar_Sql_Select’);
$select->from(‘test_tbl’,array(‘*’));
$res=$select->fetch(‘all’);
$this->res=$res;
[/php]

This example pulls the data from a test table named, creatively, test_tbl and pulls it into an array. This array is then pulled into the “res” property and added to the output of the view (as located in the View for Index).

So, there it is – that’s my experience so far with the Solar framework. It’s a little different than the other two frameworks, but I think so far, I like it a little more. It has a little lighter feel to it and doesn’t seem so much like someone dumped a toolbox over your head and told you to make sense of it all. Unfortunately, there’s still some of a learning curve to Solar. Once you get outside of the API docs on the site, there’s not a whole lot in the way of documentation. Thankfully, there’s always the guys in #solarphp on the Freenode IRC network to run to with questions.

Oh, and did I mention that the time from downloading the framework and getting all of this up and working was about 4-5 hours? Definitely works for me 🙂

Querying Arrays

Before I really get into it, I wanted to ask if anyone knew of a something already written in PHP to query arrays. Something kind of like:

[php]

$arr=array(
‘foo’=>array(
‘one’=>’this’,
‘two’=>’that’
)
);
$seek=’foo one’;

$query = new ArrayQuery($seek,$arr);

[/php]

…where $query would contain the node of key “one” and its contents, “this”. I’ve found myself needing something like this a few times recently, but haven’t been able to find something.

Does anyone know of anything like this or would find it useful in their own development work?

Is your site Quiet?

Here’s an interesting article I came across (digg) today for all those working with content heavy sites – Andy Rutledge on “Quiet Design”. In it, he compares two major online news sources – CNN.com and USAToday.com – in things like layout, object placement and things they could do to help achieve Quiet Structure over Loud Structure.

It’s interesting to see his opinion that it’s not always about dropping content on a page to make things simpler but that it’s also about where things are on the page and how they’re laid out compared to the others.

A Primer to Using Air – Followup

Well, I poked around in the AIR documentation, and I think I found their preferred method (and the only method I tried that would let me grab data from another domain) of connecting to a backend script:

[cc lang=”javascript”]

function appLoad(){
var request = new air.URLRequest(‘http://www.php.net/news.rss’);
var loader = new air.URLLoader();
loader.dataFormat=air.URLLoaderDataFormat.TEXT;
loader.addEventListener(air.Event.COMPLETE,completeHandler);
loader.load(request);
}
function completeHandler(event){
var loader2=event.target;
air.trace(loader2.data);
alert($(‘//rdf/item/title’,loader2.data).length);

$(loader2.data).find(‘item/title’).each(function(k,v){
alert(v.text());
});

$(‘item’,loader2.data).each(function(k,v){
$(‘#mytbdy’).append(‘

> ‘+v.childNodes[0].nodeValue+’

‘);
});
}

[/cc]

I think the code above’s a little flaky when it comes to inserting things back into the table, but the connection code is sound. It grabs the actual RSS file from php.net and pushed it into the table below it.