Page 1 of 1

Input Filtering on sequenced commands

Posted: Sat Oct 08, 2005 10:11 am
by Maugrim_The_Reaper
Question in relation to Input Filtering...

At the moment I'm working on an application (actually three - the code is re-usable) which utilise an input filter. One of the requirements for the input filter is to utilise a FilterData class (simply a definition of expected input data keys, value types, and validation rules). Now in the application I am utilising an Application Controller, i.e. requests can be mapped to a series of application logic parcels (basically a class using the Command pattern) and a view.

At present data is filtered once - on a per command basis. The problem is that once data is filtered for one command, it will of course filter out data required for subsequent commands (in the application controller's queue). One solution is to maintain a copy of the original input data and re-filter for every command - but that seems overkill, given the Request data (encapsulated in an object) would keep shifting and being refreshed, i.e. multiple Request object copies would be required - making the passing of Request objects throughout the application complex at best and completely confusing at worst. Sounds very messy. The other is to know all commands being called in advance - but then that requires data be filtered further into the application (rather than it being the first task performed).

Messy only begins to describe the situation...;)

Maybe its my inexperience in using an Application Controller (usually I go with FrontController or the simplicity of PageControllers where only one command is ever required, and command usually duplicate a lot of re-usable code) but is there an obvious solution for all this I am missing??? I only want each command to receive data it itself expects - in the interests of keeping any possible non-expected data leakage to the absolute minimum... Maybe this strategy is simply too strict itself...

Posted: Sat Oct 08, 2005 7:38 pm
by Ambush Commander
You have Filter Objects which contain instructions about how to filter things. These are polymorphic and can be freely interchanged. You have complex logic regarding which of these objects should be applied: there are breakpoints in the script where you apply the filter, but you might need to change the filter later.

Solution? Exactly what you said: push filtering later into the program. Factor your filter logic into two types: types that determine exactly how the data has to be filtered, and logic that requires the information be filtered.

Your filtering probably shouldn't be discarding information you need later. Perhaps you need to parse and extract the data into the multiple request objects you described as messy?

Hmm... I don't really understand, but if something I babbled about helped, then my work here is done. ;)

I really shouldn't have used the bold, but ah well. I'm being assertive, but take my statements with a healthy helping of salt.

Re: Input Filtering on sequenced commands

Posted: Sat Oct 08, 2005 10:16 pm
by McGruff
Maugrim_The_Reaper wrote: I only want each command to receive data it itself expects - in the interests of keeping any possible non-expected data leakage to the absolute minimum... Maybe this strategy is simply too strict itself...
Yes, I think so. A Request object ends up getting passed around almost everywhere and different command objects can read from it whatever they are interested in. Just to check we're on the same page, I'm assuming that by "command" you mean there are a range of possible commands associated with a single request type?

You could have a generic kind of Request object which is configured per http request type, or you can have a custom object per type (possibly extending a superclass). I prefer the latter since I like to use named getters.

Posted: Sun Oct 09, 2005 8:06 am
by Maugrim_The_Reaper
Basically at the moment I use a fairly generic Request object to pass around "filtered" data from POST/GET. It's the only Request object created - and get's passed around as a referenced parameter (thus its the only instance of the object actually used).

I don't use a dynamic form, i.e. if I need to pass additional data between layers I'll use a completely separate object, maybe a SessionData or ViewData depending on use (and to prevent any erroneous overwriting). The Request set method is actually there to facilitate unit testing (aha ;)), which I've been using with pretty positive results.
Solution? Exactly what you said: push filtering later into the program. Factor your filter logic into two types: types that determine exactly how the data has to be filtered, and logic that requires the information be filtered.
That sounds eerily like the messy solution I suggested ;). I passed over it because pushing actual filtering further back onto commands themselves seemed to be allowing unfiltered data move freely through the prior one or two layers (where it might potentially do something *bad* - more a risk than a certainty).
Your filtering probably shouldn't be discarding information you need later. Perhaps you need to parse and extract the data into the multiple request objects you described as messy?
Maybe so - but that means maintaining the original data, which in an Register_Globals On environment may be an additional security risk - which I would prefer to avoid of possible. I think maybe I AM being too strict...

The "babbling" did make sense - I thought I was the one babbling...:)
Just to check we're on the same page, I'm assuming that by "command" you mean there are a range of possible commands associated with a single request type?
Well the idea behind the system is for a Front Controller to map a request to a Handler/Command. Generally if the request will invoke a series of Commands - the FC should map to an Application Controller which can use some internal stored State to determine what Commands (whether single, or in series), and in what order, should be invoked. The term Command refers to the pattern some object containing application logic follows - basically say a DoThis or DoThat or AddThis set of objects which reflect an "action", bundled into an execute() method.

As an example, a user enacts an action which will begin a process. Now say the process requires three Commands (an object which executes a set of discrete application logic), to be run one after the other without any further input from the user. So basically you get a queue of commands to be executed. A more familiar example - though more a specialised form of the AC - might be a multi-page form, where some form pages can be skipped depending on input - the AC would control this using some internally stored State. A state could be something as simple as a flag set in $_SESSION just to show what I mean by the term. I think the term Transition is more commonly used to describe the passage of control between Commands in a queue...

Now for this example the AC would run Command1, Command2, Command3 in succession, and then invoke a View of some description. The current system would filter data based on Command1 - ignoring the rest, and deleting any data they may require since not expected by the FilterData Object for Command1. If that makes sense...;)

Back on topic...

Part of the problem is that there's no way to know beforehand which commands will be called after Command1 (i.e. there no existing State to predict that yet - since Command1 has to issue an updated State for the AC to continue to any other Command). It's beginning to look more and more like multiple Request objects isn't it?

Posted: Sun Oct 09, 2005 8:10 am
by Maugrim_The_Reaper
You could have a generic kind of Request object which is configured per http request type, or you can have a custom object per type (possibly extending a superclass). I prefer the latter since I like to use named getters.
Request itself is extended from a generic DataMap class - it follows one of those simple interfaces with a get(), set(), import(), clear() etc. methods for handling some generic Array of data. Mostly they are wrappers for something else - in Request, a wrapper over the POST/GET array. In StateData, a wrapper over $_SESSION['_statedata']... Only thing the child class requires is a construtor to set the reference to whatever source array is being wrapped...

Posted: Sun Oct 09, 2005 9:51 am
by McGruff
Maugrim_The_Reaper wrote:there's no way to know beforehand which commands will be called after Command1 (i.e. there no existing State to predict that yet - since Command1 has to issue an updated State for the AC to continue to any other Command).
I don't know exactly what you're doing, but this does sound like a new responsibility. Request is a kind of Gateway to the "outside world" - and hence can encapsualte the http or CLI contexts. Application state is something internal to the application (although you might well need to check something in Request to figure out what state you're in).

If you're having a hard time passing too many vars around all over the place, take a look at the Registry pattern.

Posted: Sun Oct 09, 2005 2:44 pm
by Maugrim_The_Reaper
Say from Command1 the ApplicationController can dispatch to either C2 or C3. It knows which because C1 will set some State flag the AC can refer to while making that decision - whether between requests, or in the same request - typically I'd use the SESSION maybe though a StateData wrapper (basically a similar interface to a Request object but separate from Request and wrapping something like a $_SESSION['_state'] array).

Think I mentioned that in the last post...

Too many vars isn't the issue (I think), though could be if I implement this multiple Filtered Request scheme ;) It's sounding more likely by the hour...lol. Well, at least one other person sees it as a solution (Ambush Commander) so I'll give it a shot and look for any sec issues after...
Ambush Commander wrote:You have Filter Objects which contain instructions about how to filter things. These are polymorphic and can be freely interchanged. You have complex logic regarding which of these objects should be applied: there are breakpoints in the script where you apply the filter, but you might need to change the filter later.

Solution? Exactly what you said: push filtering later into the program. Factor your filter logic into two types: types that determine exactly how the data has to be filtered, and logic that requires the information be filtered.
This looks like a fairly simple variation of what I have implemented already - just a matter of adding a little extra decision making between Commands, and maintaining the original input data packaged somewhere outside GET/POST.

Posted: Sun Oct 09, 2005 2:57 pm
by Maugrim_The_Reaper
Okay, shifted things around a little to get Request passed through into the Command/AC layer. From there should be simple going. If anyone sees any obvious issues in the code below, let me know. FCs in PHP seem a bit scarce on the ground, and I won't even mention ACs... :?

Code: Select all

<?php

// author: Padraic Brady
// date: 5 October 2005
// copyright (c) 2005 Padraic Brady
// licensed under the GNU General Public License v2
// Package when doc'd: Partholan

// todo: Request Filtering (multiple Request objs?), ViewHelper strategy decision (maybe a factory/abstract factory)
// v0.2

// notes: finish IFC components, clean up and finish UTs

class FrontController {
	
	var $privateFlag;
	var $requestMapper;
	var $stateData;
	var $viewData;

	function FrontController(&$requestMapper, $private=true) {
		// spit APPKEY const into DataSpaces that use SESSION (makes unique dataspace names to prevent conflicts)
		$this->privateFlag = $private;
		$this->requestMapper =& $requestMapper;
		$this->stateData =& StateData::getInstance(APPKEY); // required if handler is a Application Controller
		$this->viewData =& ViewData::getInstance(APPKEY);
	}

	function execute(&$request, &$response) {
		// IFC will construct chained actions - User Validation, Session Expiry, etc. if needed
				// a simple queue would suffice really...
		$filterChain =& InterceptingFilterChainFactory::createChain($priv =& $this->getPrivate());
		if(is_object($filterChain) && method_exists($filterChain, 'processRequest')) 
		{
			$filterChain->processRequest();
		}

		// after IFC - back to FC
		$this->doRequest($request, $response);
	}

	function doRequest(&$request, &$response) {

		$handler =& $this->requestMapper->mapCommand($request); // mapHandler (rename!)
		$this->checkPrivateFlags($handler);
		if(is_object($handler) && method_exists($handler, 'execute'))
		{
            $handler->execute($request, $response);
        }
		else 
		{
			$response->setHeader('HTTP/1.0 404 Not Found');
			$response->setContent('The page you were looking for could not be found.<br /><br />Please return to <a href="'.URLROOT.'">'.URLROOT.'</a>');
		}



		// do something to decide on View strategy - default is Smarty (shift to 'format' Request param maybe)
				// allows different template engines as a side benefit...
				// Factory smell? -will need XML/PDF ViewHelpers at a minimum
		require_once(APPROOT . 'System/Library/Abstracts/ViewHelper.php');
		require_once(APPROOT . 'System/Library/ViewHelpers/ViewHelper_Smarty.php');
		$viewHelper =& new ViewHelper_Smarty();



		$view =& $handler->getView(); // handler should determine the View to call (independent of view strategy)
		$view->process($response, $viewHelper); // imports viewData into Smarty VH, adds parsed template to Response

		$this->viewData->clear(); // delete temporary viewData (no longer needed)

		$response->output(); // at long last, output our content 
	}

	function getPrivate() {
		return $this->privateFlag;
	}

	function checkPrivateFlags(&$handler) {
		$c_private = $handler->getPrivate();
		if(!isset($c_private) || !is_bool($c_private)) 
		{
			trigger_error('It is not not defined whether this Handler Object is private (requires authentication) or public (no authentication) - a Handler::privateFlag property must be set to a boolean value (TRUE or FALSE)', E_USER_ERROR);
		}
		if($this->getPrivate() !== $c_private) 
		{
			trigger_error('privateFlag flag of FrontController does not match privateFlag flag of the Handler object - these must match for a Handler to proceed', E_USER_ERROR);
		}
	}

}

?>

Posted: Mon Oct 10, 2005 4:47 pm
by Christopher
I am not clear exactly what you are doing here, but I recommend separating your Filtering from your Validation as they are two distinct things. And as mentioned here, filter from the request to a local/property and then validate, only dealing with the request vars that the code is interested at each point.