I'll use preg_match, because the manual says it's faster:
<?php
$fname[] = "abr234akadabra?txt";
$fname[] = "abr234akadabra/txt/";
$fname[] = "abr234akadabra\\txt";
$fname[] = "\"abr234akadabratxt";
$fname[] = "abr234akad.YYYabra_txt";
foreach ($fname as $str)
if(preg_match('|^[a-z0-9_.]*$|i', $str))
{
echo "<i>$str</i> <b>passed</b> the test.<br>";
}
else {
echo "<i>$str</i> <b>failed</b>.<br>";
}
?>
And now some explanation. In regular expression "|" means the beginning and the end of regex. After the end there is an option "i", meaning the search should be case insensitive. The main difference however lies in "" and "$". They mean that the match should start at the beginning and end with the end of a string. Without it, preg_match looks for any substring. So in the first string it finds "abr234akadabra" even though the next character, question mark, isn't valid. The result without $ would be true. With them, it's false.
Oh, and the result of the script above is:
abr234akadabra?txt failed.
abr234akadabra/txt/ failed.
abr234akadabra\txt failed.
"abr234akadabratxt failed.
abr234akad.YYYabra_txt passed the test.