windows to openbsd transition has caused script to not work

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
peterg
Forum Newbie
Posts: 4
Joined: Thu Mar 15, 2007 8:38 pm

windows to openbsd transition has caused script to not work

Post by peterg »

Hello,
I recently wrote a php script to parse an external xml file, and organise its content into news posts, "archiving" older posts by putting them on separate pages. You can see how this works by visiting my website, http://petergeoghegan.com. This is my first real php script. The code is as follows:

Code: Select all

<?PHP
$news = fopen("news.xml", "rb");
$usable = fread($news,4096);
fclose($news);
$parser = xml_parser_create('UTF-8');
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 
xml_parse_into_struct($parser, $usable, $vals, $index); 
xml_parser_free($parser);
// change this variable, "$postsperpage" , to adjust the number of posts you'd like to see per page
$postsperpage = 5;
//first, to determine the total number of posts and pages in the xml file/mirrored array
$numberofposts = count($index[TITLE]);
if ($numberofposts > $postsperpage){
$numberofpagesflat = round($numberofposts / $postsperpage );}
else{
$numberofpagesflat = 1;}
$belessthen = $numberofposts / $postsperpage;
if ($numberofpagesflat < $belessthen){
// above if is evaluated as true, even if it shouldn't. Why?
$numberofpagesflat ++;}
//news item printing loop
if (empty($_GET["post"]) or $_GET["post"] > $numberofpagesflat)
$newsitem = $postsperpage;
else
$newsitem = $_GET["post"] * $postsperpage;
for ($increment = $newsitem - $postsperpage; $increment < $newsitem and $increment < $numberofposts; $increment++) 
{
echo "<p><big>{$vals[$index[TITLE][$increment]][value]}</big></p>\n";
echo "<p><date>{$vals[$index[DATEPOSTEDBY][$increment]][value]}</date></p>\n";
// use incrementation to mark all relevant arrays for printing as part of the body tag, then print them.
$bodyincrement = $increment * 2;
$start = $index[BODY][$bodyincrement];
$end = $index[BODY][$bodyincrement + 1];
//While loop prints all body segment arrays together
while ( $start <= $end){
if ($vals[$start][type] == "open" and empty($vals[$start][attributes][HREF])){
echo '<'; 
echo mb_strtolower($vals[$start][tag]);
echo '>';
echo $vals[$start][value];
}
elseif ($vals[$start][type] == "close" ){
echo $vals[$start][value];
echo '</'; 
echo mb_strtolower($vals[$start][tag]);
echo '>';}
elseif ($vals[$start][type] == "cdata"){
echo $vals[$start][value];}
elseif ($vals[$start][type] == "complete" and empty($vals[$start][attributes]))
{
echo '<';
echo mb_strtolower($vals[$start][tag]);
echo '>';
echo $vals[$start][value];
echo '</';
echo mb_strtolower($vals[$start][tag]);
echo '>';
}
elseif($vals[$start][type] == "complete" and !empty($vals[$start][attributes][HREF])){
echo '<';
echo mb_strtolower($vals[$start][tag]);
echo ' href="';
echo $vals[$start][attributes][HREF];
echo '">';
echo $vals[$start][value];
echo '</';
echo mb_strtolower($vals[$start][tag]);
echo '>';
}
elseif($vals[$start][type] == "open" and !empty($vals[$start][attributes][HREF])){
echo '<';
echo mb_strtolower($vals[$start][tag]);
echo ' href="';
echo $vals[$start][attributes][HREF];
echo '">';
}
elseif($vals[$start][type] == "complete" and $vals[$start][tag] == "IMG"){
echo '<';
echo mb_strtolower($vals[$start][tag]);
echo ' src="';
echo $vals[$start][attributes][SRC];
echo '" alt="';
echo $vals[$start][attributes][ALT];
echo '"/>';
}
else
{
echo $vals[$start][value];}
$start ++;
}
if ($increment < ($newsitem -1) and $increment < ($numberofposts - 1 )){
$psuedorandom = rand(1, 3);
echo '<p align="center"><img src="images/seperator';
echo $psuedorandom;
echo '.png" alt="*" align="middle"/></p>';
}}
//news archive printing loop
if ($numberofposts > $postsperpage){
echo "<p>News archive: ";
$switch = 0;
for ($tracker = 1; $tracker <= $numberofpagesflat; $tracker++)
{
// this first if isn't relevant, so long you opt not to have an archive bit built at all by using a master if statement. it is left here in case you change your mind
if ($numberofposts <= $postsperpage){
echo "1 ";
$tracker = $numberofpagesflat;
}
elseif ($_GET["post"] == $tracker){
echo "$tracker ";
}
elseif (empty($_GET["post"]) and $switch == 0)
{
echo "1 ";
$switch++;
}
else{
echo '<a href="?page=home&post=';
echo $tracker;
echo '">';
echo $tracker;
echo '</a> ';
}
}
echo "</p>";
}
?>
This works fine on my windows 2003/iis server, but I can't seem to get it to work properly on my Open BSD server. The first headline of the home page will print, but nothing any further down then that. I'm using the version of php that is available as an Open BSD package. In keeping with Open BSD's ethos, this version of php has a non-standard php.ini file that restricts various things in the interest of security, which is the cause of the problem, I suspect. I imagine it would take me a long time to isolate this cause any further, so I'd appreciate it if someone pointed me in the right direction,
Regards,
Peter Geoghegan
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

Wow. Your code is unbelievably hard to read. Let's clean it up a bit (and fix some errors,) shall we?

Code: Select all

<?PHP

error_reporting(E_ALL);
ini_set('display_errors', true);

$news = fopen("news.xml", "rb");
$usable = fread($news,4096);
fclose($news);
$parser = xml_parser_create('UTF-8');
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, $usable, $vals, $index);
xml_parser_free($parser);

// change this variable, "$postsperpage" , to adjust the number of posts you'd like to see per page
$postsperpage = 5;

//first, to determine the total number of posts and pages in the xml file/mirrored array
$numberofposts = count($index['TITLE']);

if ($numberofposts > $postsperpage)
{
	$numberofpagesflat = round($numberofposts / $postsperpage );
}
else
{
	$numberofpagesflat = 1;
}

$belessthen = $numberofposts / $postsperpage;

if ($numberofpagesflat < $belessthen)
{
	// above if is evaluated as true, even if it shouldn't. Why?
	$numberofpagesflat ++;
}

//news item printing loop
if (empty($_GET["post"]) or $_GET["post"] > $numberofpagesflat)
	$newsitem = $postsperpage;
else
	$newsitem = $_GET["post"] * $postsperpage;

for ( $increment = $newsitem - $postsperpage;
      $increment < $newsitem and $increment < $numberofposts;
      $increment++ )
{
	echo '<p><big>' . $vals[$index['TITLE'][$increment]]['value'] . '</big></p>' . "\n";
	echo '<p><date>' . $vals[$index['DATEPOSTEDBY'][$increment]]['value'] . '</date></p>' . "\n";
	
	// use incrementation to mark all relevant arrays for printing as part of the body tag, then print them.
	$bodyincrement = $increment * 2;
	
	$start = $index['BODY'][$bodyincrement];
	
	$end = $index['BODY'][$bodyincrement + 1];
	
	//While loop prints all body segment arrays together
	while ( $start <= $end )
	{
		if ($vals[$start]['type'] == "open" and empty($vals[$start]['attributes']['HREF']))
		{
			echo '<';
			echo mb_strtolower($vals[$start]['tag']);
			echo '>';
			echo $vals[$start]['value'];
		}
		elseif ($vals[$start]['type'] == "close" )
		{
			echo $vals[$start]['value'];
			echo '</';
			echo mb_strtolower($vals[$start]['tag']);
			echo '>';
		}
		elseif ($vals[$start]['type'] == "cdata")
		{
			echo $vals[$start][value];
		}
		elseif ($vals[$start]['type'] == "complete" and empty($vals[$start]['attributes']))
		{
			echo '<';
			echo mb_strtolower($vals[$start]['tag']);
			echo '>';
			echo $vals[$start]['value'];
			echo '</';
			echo mb_strtolower($vals[$start]['tag']);
			echo '>';
		}
		elseif($vals[$start]['type'] == "complete" and !empty($vals[$start]['attributes']['HREF']))
		{
			echo '<';
			echo mb_strtolower($vals[$start]['tag']);
			echo ' href="';
			echo $vals[$start]['attributes']['HREF'];
			echo '">';
			echo $vals[$start]['value'];
			echo '</';
			echo mb_strtolower($vals[$start]['tag']);
			echo '>';
		}
		elseif($vals[$start]['type'] == "open" and !empty($vals[$start]['attributes']['HREF']))
		{
			echo '<';
			echo mb_strtolower($vals[$start]['tag']);
			echo ' href="';
			echo $vals[$start]['attributes']['HREF'];
			echo '">';
		}
		elseif($vals[$start]['type'] == "complete" and $vals[$start]['tag'] == "IMG")
		{
			echo '<';
			echo mb_strtolower($vals[$start]['tag']);
			echo ' src="';
			echo $vals[$start]['attributes']['SRC'];
			echo '" alt="';
			echo $vals[$start]['attributes']['ALT'];
			echo '"/>';
		}
		else
		{
			echo $vals[$start]['value'];
		}
		$start ++;
	}
	if ($increment < ($newsitem -1) and $increment < ($numberofposts - 1 ))
	{
		$psuedorandom = rand(1, 3);
		echo '<p align="center"><img src="images/seperator';
		echo $psuedorandom;
		echo '.png" alt="*" align="middle"/></p>';
	}
}

//news archive printing loop
if ($numberofposts > $postsperpage)
{
	echo "<p>News archive: ";
	
	$switch = 0;
	
	for ($tracker = 1; $tracker <= $numberofpagesflat; $tracker++)
	{
		// this first if isn't relevant, so long you opt not to have an archive bit built at all by using a master if statement. it is left here in case you change your mind
		if ($numberofposts <= $postsperpage)
		{
			echo "1 ";
			$tracker = $numberofpagesflat;
		}
		elseif ($_GET["post"] == $tracker)
		{
			echo "$tracker ";
		}
		elseif (empty($_GET["post"]) and $switch == 0)
		{
			echo "1 ";
			$switch++;
		}
		else
		{
			echo '<a href="?page=home&post=';
			echo $tracker;
			echo '">';
			echo $tracker;
			echo '</a> ';
		}
	}
	echo "</p>";
}
?>
Now, how does it run?
peterg
Forum Newbie
Posts: 4
Joined: Thu Mar 15, 2007 8:38 pm

Post by peterg »

I'm getting the following error message with that code, which I also get if I amend

Code: Select all

error_reporting(E_ALL);
ini_set('display_errors', true);
to the original code:

Fatal error: Call to undefined function: mb_strtolower() in /htdocs/xmlparser.php on line 63

I tried replacing my php.ini with the one that comes bundled with generic php, but it didn't help. Why should the function mb_strtolower() need to be defined if it's a built-in function? I went to the mb_strtolower() page on php.net, and it said that it was only supported in PHP 4 >= 4.3.0, PHP 5. I thought that was the problem, until I remembered that I originally installed php 5 on my new Open BSD box, had the same problem and assumed it was because this script used some deprecated php4-only code (I guess thats why they still maintain php4, right?), and so replaced php5 with php4. Because I never had error reporting on with php5, it's possible (though unlikely) I had an unrelated error that manifested itself in exactly the same way. Your thoughts?,
Regards,
Peter Geoghegan

p.s I've overlooked some redundant comments that were left in my code. Apologies for any confusion caused, I didn't think I'd have to show it to anyone.
User avatar
dude81
Forum Regular
Posts: 509
Joined: Mon Aug 29, 2005 6:26 am
Location: Pearls City

Post by dude81 »

I doubt your configuration. Check --enable-mbstring is enabled or not using phpinfo();
peterg
Forum Newbie
Posts: 4
Joined: Thu Mar 15, 2007 8:38 pm

Post by peterg »

Dude81,
There is no reference to mbstring in my phpinfo. I don't think mbstring is a particularly significant function - it just changes the case of a given string. Why should any setting related to mbstring vary from one distribution of php to another? When php's XML parser created an array with upper case xml tags, I used mbstring to make my html tags lower case again, so that the document validated as xhtml.
User avatar
dude81
Forum Regular
Posts: 509
Joined: Mon Aug 29, 2005 6:26 am
Location: Pearls City

Post by dude81 »

In Multibyte string functions I see it as required
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

peterg wrote:Why should the function mb_strtolower() need to be defined if it's a built-in function? I went to the mb_strtolower() page on php.net, and it said that it was only supported in PHP 4 >= 4.3.0, PHP 5.
mb_strtolower() is part of the module mbstring.
http://sg.php.net/manual/en/ref.mbstring.php wrote:mbstring is a non-default extension. This means it is not enabled by default. You must explicitly enable the module with the configure option.
Exactly what and how did you install on your BSD box?
peterg
Forum Newbie
Posts: 4
Joined: Thu Mar 15, 2007 8:38 pm

Post by peterg »

Volka, Dude, feyd

This must be the problem. I'm sure that if I install the mbstring package (In bsd parlance, package is a binary distribution), everything will work. I had assumed that this was part of the php core. Thank you all.
Post Reply