Archive

Posts Tagged ‘filter’

FilterChain Element In Phing

January 12th, 2009 No comments

The FilterChain element is where the power of Phing really comes into its own. This element will allow you to change the contents of the files of a fileset. This can range from a simple stripping of comments, to replacing values and numerous other filters.

One of the simplest thing that can be done with filterset is to strip all comments from the files in question. Take the following PHP file with two comments.

<?php
/**
 *
 * This is a comment
 *
 *
 **/
echo 'Hello World!';
 
// another comment.

These comments can be stripped out of the file by using the stripphpcomments element. This is added to the copy element in the following way.

<?xml version="1.0"?>
<!-- build xml -->
 <project name="myProject" default="main">
 
 <fileset dir="./" id="myProjectFiles">
  <include name="**/*.php" />
  <exclude name="myProject_build/**" />
 </fileset>
 
 <target name="main">
  <copy todir="./myProject_build">
   <fileset refid="myProjectFiles" />
   <filterchain>
    <stripphpcomments />
   </filterchain>
   </copy>
 </target>
</project>

The PHP file now looks like this.

<?php
 
echo 'Hello World!';
 
 
 

Although this might be a nightmare to maintain it might be useful if reducing the size of your files is necessary. You might want to do this if you plan to sell your PHP software as it would make alteration by your customer a little bit more difficult.

Another use of the filterchain is to replace values within the code base. This is useful if you want to set a version number or a default database password. To replace a token with a value you need a property that can will store the value. You then need to go into your source code and replace any instance of the term you want to replace with the property name within @ symbols. Take the following PHP file.

<?php
/**
 *
 * This is a comment
 *
 *
 **/
$property1 = '@myProperty@';
echo 'Hello World!';
 
// another comment.

To replace the myProperty property with the value of "test", you need to use the replacetokens element, which can contain one or more token elements. The following build.xml file will replace all instances of the key myProperty with the value "test".

<?xml version="1.0"?>
<!-- build xml -->
 <project name="myProject" default="main">
 <property name="myProperty" value="test" />
 
 <fileset dir="./" id="myProjectFiles">
  <include name="**/*.php" />
  <exclude name="myProject_build/**" />
 </fileset>
 
 <target name="main">
  <copy todir="./myProject_build">
   <fileset refid="myProjectFiles" />
   <filterchain>
    <replacetokens>
      <token key="myProperty" value="${myProperty}" />
    </replacetokens>
   </filterchain>
   </copy>
 </target>
</project>

You will now see in your build output something like the following:

[filter:ReplaceTokens] Replaced "@myProperty@" with "test"

The token in each of the files will now be changed with the value of the property.

To see a list of the core filters available, take a look at the Phing filter appendix on the Phing website. You can even do something odd like only include the first 3 lines from each file, and append each line with the word "wibble".

<filterchain>
 <headfilter lines="3" />
 <prefixlines prefix="wibble: " />
</filterchain>

I can see why the headfilter might be useful in some instances where you want to test that your build file adds the correct file to each folder/zip file without including the whole thing. But where would you ever need to append a string to every line?

One final thing, if you change anything within your build file that replaces values then remember that phing will save time by not copying across any file that has already been copied and that hasn’t changed. This means that if you change a filter and update you will see no changes unless you do one or both of the following:

  • Manually delete any files in the target directories.
  • Add an overwrite attribute to the copy element(s) in your target element(s). This will force phing to simply overwrite the files every time, even if they haven’t changed.

Simple Swear Filter In PHP

September 30th, 2008 No comments

Use the following function to filter out words from user input. It works by having a pre-set array of words that are to be excluded, this array is then looped through and each item is used to replace any instances of that word within the text. The regular expression uses the \b character class, which stands for any word boundary. This way you don’t get the middle of words being filtered out when they are not meant to be.

By using the e of the preg_replace function it is possible to run PHP functions within the output. In this case we count the number of characters found in the replace and use this to create a string of stars (*) of equal length.

function filterwords($text){
 $filterWords = array('gosh','darn','poo');
 $filterCount = sizeof($filterWords);
 for($i=0; $i<$filterCount; $i++){
  $text = preg_replace('/\b'.$filterWords[$i].'\b/ie',"str_repeat('*',strlen('$0'))",$text);
 }
 return $text;
}

When the following text is run through this function.

echo filterwords('Darn, I have a mild form of torretts, poo!');

It produces the following result.

****, I have a mild form of torretts, ***!

Categories: PHP Strings Tags: , , , , , ,

Add Effects To Images Using Image Filters With PHP

July 24th, 2008 2 comments

The imagecreatefromjpeg() function has been part of the PHP library since version 4, allowing programmers to load an image directly from a file. However, the imagefilter() has only been available since version 5 and adds a nice little set of effects to an already useful function.

The effects are created using the function in conjunction with a set of constants. Take the following image taken from the free stock images site.

Default Electronics image

I chose this images because it has lots of colour and will show the techniques working well. To create the effects you need to use the following bit of code, in this case I am using the negative filter.

header("content-type: image/png");
$image = imagecreatefromjpeg("tech03250023.jpg");
imagefilter($image,IMG_FILTER_NEGATE);
imagepng($image);
imagedestroy($image);

You can also use imagecreatefromgif() and imagecreatefrompng(), but I have found mixed results with these functions. I think this is because it is possible to create a custom pallets for these formats, which causes some of the filters not to work properly. It isn’t possible to get a custom pallet for a JPG image, so they are probably the best image format to use.

Here is a list of the filters that you can use with this function. In each case the code used to generate the image and the image produced are displayed.

IMG_FILTER_NEGATE : This filter reverses all of the colours in the image, making it look like a photograph negative.
imagefilter($image,IMG_FILTER_NEGATE);
Default Electronics image IMG_FILTER_NEGATE

IMG_FILTER_GRAYSCALE :
This converts the image to black and white.
imagefilter($image,IMG_FILTER_GRAYSCALE);
Default Electronics image IMG_FILTER_GRAYSCALE

IMG_FILTER_BRIGHTNESS :
This changes the brightness of the image. In this instance the imagefilter() function takes an additional 3rd parameter, which is the level of brightness. This number ranges from -255 (black) to 255 (white). Any number higher or lower than this would cause the filter to be ignored.
imagefilter($image,IMG_FILTER_GRAYSCALE,150);
Default Electronics image IMG_FILTER_BRIGHTNESS

IMG_FILTER_CONTRAST :
Changes the contrast of the image. In this case the imagefilter() function takes an additional 3rd parameter, which is the level of contrast, much like the IMG_FILTER_BRIGHTNESS filter.
imagefilter($image,IMG_FILTER_CONTRAST,150);
Default Electronics image IMG_FILTER_CONTRAST

IMG_FILTER_COLORIZE :
With this filter you can alter the saturation of a colour within your image. The function takes an additional 3 parameters, which are the level of red, blue and green, in that order. Each level goes from 0 to 255.
imagefilter($image,IMG_FILTER_COLORIZE, 0, 255, 0);
Default Electronics image IMG_FILTER_COLORIZE

IMG_FILTER_EDGEDETECT :
This filter uses edge detection to highlight the edges in the image.
imagefilter($image,IMG_FILTER_EDGEDETECT);
Default Electronics image IMG_FILTER_EDGEDETECT

IMG_FILTER_EMBOSS :
Adds an emboss to the image.
imagefilter($image,IMG_FILTER_EMBOSS);
Default Electronics image IMG_FILTER_EMBOSS

IMG_FILTER_SELECTIVE_BLUR :
Blurs the image using a non-gaussian method.
imagefilter($image,IMG_FILTER_SELECTIVE_BLUR);
Default Electronics image IMG_FILTER_SELECTIVE_BLUR

IMG_FILTER_GAUSSIAN_BLUR :
This adds a gaussian blur to the image.
imagefilter($image,IMG_FILTER_GAUSSIAN_BLUR);
Default Electronics image IMG_FILTER_GAUSSIAN_BLUR

IMG_FILTER_MEAN_REMOVAL :
Uses mean removal to achieve a "sketchy" effect.
imagefilter($image,IMG_FILTER_MEAN_REMOVAL);
Default Electronics image IMG_FILTER_MEAN_REMOVAL

IMG_FILTER_SMOOTH :
This runs a smooth filter over the image. The additional parameter in this case is the level of smoothing.
imagefilter($image,IMG_FILTER_SMOOTH,50);
Default Electronics image IMG_FILTER_SMOOTH

Combinations
It is also possible to combine the effects together and layer filters on top of each other. The image below is created through a combination of different filters.

imagefilter($im,IMG_FILTER_BRIGHTNESS,150);
imagefilter($im,IMG_FILTER_EMBOSS);
imagefilter($im,IMG_FILTER_BRIGHTNESS,150);
imagefilter($im,IMG_FILTER_GAUSSIAN_BLUR);
imagefilter($im,IMG_FILTER_SELECTIVE_BLUR);
imagefilter($im,IMG_FILTER_MEAN_REMOVAL);
imagefilter($im,IMG_FILTER_SMOOTH,50);

Default Electronics image Combination

You might not see much difference with the blur filters, but I think it matters what image is chosen for it. The image selected for this test is slightly blurred anyway, so adding blur to this seems not to do very much.

Categories: PHP Tags: , , , , ,

PHP Filter FILTER_VALIDATE_URL Limitations

April 8th, 2008 3 comments

I have previously talked about the filterfunctions available in PHP5, but failed to spot this limitation when I was doing the research for those articles. It appears that the filter to validate URL string, namely FILTER_VALIDATE_URL, is not really adequate to the task.

Take the following examples of the filter in an if statement.
if(filter_var($url,FILTER_VALIDATE_URL)){
 return true;
}else{
 return false;
};

This will return true if the URL is valid and false if the URL is invalid. To test this I plugged the following URL strings into the function and recorded each of the outcomes.

$url = 'http://www.bbc.co.uk'; // true
$url = 'http://www.talkincode.com'; // true
$url = 'http://.com'; // true
$url = 'http://...'; // true
$url = 'http://'; // false
$url = 'http://i\'mreally trying to break this url!!!"£$"%$&*()'; // false

As you can see most of the URL I tried with this function worked, even though only the first two should actually be valid. What this filter seems to do is that it just runs the string against the parse_url() function and then detects if an array is produced. This is clearly not good enough.

All I can suggest for the time being is that you go back to using regular expressions to test for the URL validity. I picked this one up from the regular expressions library by doing a quick search for URLs.

^(http\:\/\/[a-zA-Z0-9_\-]+(?:\.[a-zA-Z0-9_\-]+)*\.[a-zA-Z]{2,4}(?:\/[a-zA-Z0-9_]+)*(?:\/[a-zA-Z0-9_]+\.[a-zA-Z]{2,4}(?:\?[a-zA-Z0-9_]+\=[a-zA-Z0-9_]+)?)?(?:\&[a-zA-Z0-9_]+\=[a-zA-Z0-9_]+)*)$

PHP5 Filter Functions Part 2

March 15th, 2008 No comments

Following on from the previous post about the PHP filter functions there are two more filter functions that require some extra explanation. These functions are filter_var_array() and filter_input_array().

They work in much the same way as filter_var() and filter_input() but they accept an array as the input. This enables you to sanitize or validate many different variables at the same time.

The first step in using these functions is to create a argument array. This is an associative array of data identifiers that allow you to set filter and sanitizer flags for different values. For example, assume that the following array is going to be used.

$data = array(
 'rowid' => '10',
 'level' => '23',
 'text' => 'some <strong>text</strong>',
 'dataAray' => array('2', '23', '10', '12'),
);

To ensure that the rowid is always an integer the filter flag FILTER_VALIDATE_INT is used in the argument array like this.

$args = array('rowid' => FILTER_VALIDATE_INT);

The same thing needs to be done to the level value in the array. However, I also need to make sure that the value is between a certain range. This is done using an inner array containing the arguments filter (to validate the integer) and options (to define a minimum and maximum range).

$args = array(
 'rowid' => FILTER_VALIDATE_INT,
 'level' => array(
  'filter' => FILTER_VALIDATE_INT,
  'options' => array(
   'min_range' => 1,
   'max_range' => 30
  )
 )
);

Anything that isn’t included in this argument array is not returned from the functions. So at the moment the functions would completely miss out the text and dataArray parts of the array. As the text variable has some HTML in it I want to use the FILTER_SANITIZE_SPECIAL_CHARS to turn this into character encoded text. The dataArray has to be all integers and I want to force this to be an array, even if it isn’t. Even if the variable is an array the FILTER_VALIDATE_INT filter will

$args = array(
 'rowid' => FILTER_VALIDATE_INT,
 'level' => array(
  'filter' => FILTER_VALIDATE_INT,
  'options' => array(
   'min_range' => 1,
   'max_range' => 30
  )
 ),
 'text' => FILTER_SANITIZE_ENCODED,
 'dataAray' => array(
  'filter' => FILTER_VALIDATE_INT,
  'flags' => FILTER_FORCE_ARRAY,
 )
);

With the array in place we can now put it into the filter_var_array() and filter/sanitize the data.

$myinputs = filter_var_array($data,$args);
 
var_dump($myinputs);

This produces the following result.

array(4) {
 ["rowid"]=>
 int(10)
 ["text"]=>
 string(42) "some text"
 ["level"]=>
 int(23)
 ["dataAray"]=>
 array(4) {
  [0]=>
  int(2)
  [1]=>
  int(23)
  [2]=>
  int(10)
  [3]=>
  int(12)
 }
}

Using this with the filter_input_array() function is just the same, but in this case instead of the data as the first parameter we use one of INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER, INPUT_ENV, INPUT_SESSION, or INPUT_REQUEST. The following example uses INPUT_POST to retrieve the data from a post request.

$myinputs = filter_input_array(INPUT_POST,$args);
 
var_dump($myinputs);

The callback filters can be used to change data from one form into another, basically creating your own sanitizers. Lets say that we had a HTML string, but that we only wanted to change three characters from their non-encoded forms to their encoded forms. These characters are <, > and ", which translate into &lt;, &gt; and &quot; respectively.

To run a callback function via a filter we use the FILTER_CALLBACK flag with an options array that points to the function we want to run.

function replaceTags($html){
 return str_replace(array('<','>','"'),array('&lt;','&gt;','&quot;'),$html);
}
 
$html = 'Some <strong style="padding:10px;">text</strong>';
 
echo filter_var($html,FILTER_CALLBACK,array('options'=>'replaceTags'));

When the filter_var() function is run in this bit of code it replaces the three characters in the HTML with their encoded equivalents.

Although there is plenty of information available on the php.net site there is a fantastic page at phpro.org that has examples on every filter and sanitizer used with the filtering functions.