Mar
3
2010
Feb
16
2010

Fix PHP unknown Error 324

When I debugged an PHP application, an mystery error message show up. Google Chrome shows the following message:

This webpage is not available.

The webpage at XXXXXX might be temporarily down or it may have moved permanently to a new web address.

More information on this error

After click the plus sign at the last sentence, I got the following error message:

Error 324 (net::ERR_EMPTY_RESPONSE): Unknown error.

I tried several ways to found what is going on. I failed to get any useful information. It is a mystery for me. I googled “PHP Error 324 (net::ERR_EMPTY_RESPONSE): Unknown error” and found the following page “http://bugs.php.net/bug.php?id=47948” at PHP.NET. Based on what I read on this page, I checked my code and found that I did initialize class A at the constructor of Class B and initialize Class B at the constructor of Class A. This kind of cyclic initialization of two classes generated the mystery error. After I removed initialization of Class B from Class A, the error was gone. I have to work out other solution to get around the dilemma.

This might be a bug in PHP release version. It seems that a complete solution has not found in the PHP development side.

  • Share/Bookmark
Jan
11
2010

Fetch files from remote server automatically in PHP

PHP provides multiple ways to download and upload files to remote servers, such as fopen, fsockopen, cURL library, and other methods. fopen is the simplest but not the best. A while ago I wrote a function to fetch remote file by using fsockopen. However, I found a lot of problems when I use it. Then I read the PHP Cookbook and decided to try cURL library. After I implemented it in the independent class, it works like a charm. The following is the class source code.

<?php
// completed and tested on Jan 6, 2010
// Author: Zhanshan Dong
// I adopt cURL library to download files
// It is reliable and fast, less hassle than fopen/fsockopen etc.

// this following three lines include testing code
// $file = new Remotefile("http://downloads.pcworld.com/pub/new/patches___drivers/utilities/framxpro.zip");
// $file->save2file("");

class Remotefile
{
	// the url components
	private $url = "";
	// data get back from server
	private $header  = array();
	private $content = "";
	private $extension = "";

	function __construct($url)
	{
		$this->initialize($url);
	}

	private function curl_url()
	{
		$c = curl_init($this->url);
		curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
		curl_setopt($c, CURLOPT_HEADER, 1);
		$buffer = curl_exec($c);
		curl_close($c);

		// process data
		$rnrn = "\r\n\r\n";
		$pos = strpos($buffer,$rnrn);

		if($pos === false)
		{
			// string $rnrn NOT found in $buffer
		 	echo "Something is not correct!<br />";
		}
		else
		{
			// string $rnrn found in $buffer
			$this->content = substr($buffer, $pos+4);
			$header = substr($buffer, 0, $pos);
			$this->processHeader($header);
		}
	}

	private function initialize($url)
	{
		// initialize all variables
		$this->url = $url;
		// fetch the remote file
		$this->curl_url();
	}

	private function processHeader($header)
	{
		$lines = explode("\r\n", $header);
		$this->header["status"] = $lines[0];
		foreach($lines as $line)
		{
			$data = explode(": ",$line);
			if ($data[1] != "")
			{
				$this->header[$data[0]] = $data[1];
			}
//echo "$data[0] |===| $data[1]<br />";
		}
	}

	private function redirectedURL()
	{
		return $this->header["Location"];
	}

	private function getMIMEtype()
	{
		// check redirection url
		$rdurl = $this->redirectedURL();
		if ($rdurl)
		{
			$ext = ereg_replace("^.+\\.([^.]+)$", "\\1", $rdurl);
			$this->extension = $ext;
		}
		else
		{
			$mtype = $this->header["Content-Type"];
			$temps1 = split("/",$mtype);
			$temps2 = split(";",$temps1[1]);
			$ext1 = $temps2[0];
			$this->extension = $ext1;
			if (($temps1[0] == "application"))
			{
				$ext2 = ereg_replace("^.+\\.([^.]+)$", "\\1", $this->url);
				if ($ext2)
				{
					$this->extension = $ext2;
				}
			}
      	}
      	$this->extension = trim($this->extension);
//echo "file extension = ".$this->extension."<br />";
	}

	function getHeader()
	{
		return $this->header;
	}

	function getContent()
	{
		return $this->content;
	}

	function save2file($folder)
	{
		// write to file
		$this->getMIMEtype();
		$filename = date('YmdHis').".".$this->extension;
		$target_path = getcwd();
		if ($folder)
		{
			$target_path .= "/$folder";
		}
		$target_path .=  "/".$filename;
		$Handle = fopen($target_path, 'w');
		fwrite($Handle, $this->content);
		fclose($Handle);
		return $filename;
	}

}

?>
  • Share/Bookmark
Jan
3
2010

Tips for website development

I have encountered surprised issues when I developed Bookmark Manager 2.0. They were solved successfully after I spent a significant amount of time. To share my ideas and thought with friends, I summarized the processes and generated a list of a good practices as the following.

HTML/XHTML validation
It will always be a good practice to validate your webpages after the alpha or beta version of your website is built. If the XHTML format is adopted, the practice is more important. To do that there are a couple of choices:

I personally like the first one. It can provide a lot of detail and easy to understand. You should check your code to correct all the errors based on the validation output. After all errors are fixed, your pages are more stable than ever. When you adopt XHTML, the most common error is the close tag, for example, <br /&gt vs <br>, <script ….><script> vs <script …. />.

JavaScript
Problem A: JavaScript does not run in IE and FireFox while it works fine in Google Chrome
Solution: Use encodeURL function to encode URL parameter in xmlhttp2.open(“GET”,url,true) statement, such as “xmlhttp2.open(“GET”,encodeURI(url),true);”.

Problem B: After the above changes, Opera, Safrari, IE, Chrome but FireFox are working properly. It is hard to find what was wrong in FireFox before I get FireBug extention. The problem is that FireFox cannot use the form name to refer the html element, such as “searchform.keyword.value”.
Solution: To solve the problem, have to use the “document” object to get it, for example, “window.document.forms["searchform"].elements["keyword"].value”. After the change, the JavaScript works fine for all major browsers: Chrome, IE, Sarafi, FireFox, and Opera.

Debugging Tools
FireBug is a great tool to debug the css, html, JavaScript and more.

  • Share/Bookmark
Jan
1
2010

A PHP class for manipulation of dates

The following PHP code includes a simple class that can manipulate dates, such as date subtraction, adding days and subtracting days to the current date. It is very useful because my PHP server does not support the latest DateTime function yet.

<?php

class Dt
{
	private $day;
	private $month;
	private $year;
	private $seconds=86400;

	function __construct()
	  {
		$this->day=date("j");
		$this->month=date("n");
		$this->year=date("Y");
	  }

	function now_diff($by,$bm,$bd)
	   {
		$bm=preg_replace("/[0](.+)/is","\\1",$bm);
		$bd=preg_replace("/[0](.+)/is","\\1",$bd);
		$bt=mktime(0,0,0,$bm,$bd,$by);
		$nt=mktime(0,0,0,$this->month,$this->day,$this->year);
		$df=$nt-$bt;
		$dn=$df/$this->seconds;
		return $dn;
	  }

	function date_diff($by,$bm,$bd,$ty,$tm,$td)
	   {
		$bm=preg_replace("/[0](.+)/is","\\1",$bm);
		$bd=preg_replace("/[0](.+)/is","\\1",$bd);
		$bt=mktime(0,0,0,$bm,$bd,$by);
		$nt=mktime(0,0,0,$tm,$td,$ty);
		$df=$nt-$bt;
		$dn=$df/$this->seconds;
		return $dn;
	  }

	function earlydate($ndays)
	  {
		$nt=mktime(0,0,0,$this->month,$this->day,$this->year);
		$ds=$ndays*$this->seconds;
		return $nt-$ds;
	  }

	function latedate($ndays)
	  {
		$nt=mktime(0,0,0,$this->month,$this->day,$this->year);
		$ds=$ndays*$this->seconds;
		return $nt+$ds;
	  }

}

?>
  • Share/Bookmark
Jan
1
2010

A PHP class for generating tag clouds

The following PHP code is a simple class that can generate tag cloud in any web pages.

<?php

class TagCloud
{
	private $_counts = array();
	private $_tags = array();
	private $_urls = array();
	private $_levels = array();
	private $__level = 10;

	function __construct()
	{
	}

	function add($tag,$count,$url)
	{
		$this->_counts[$tag] = "$count";
		$this->_tags[$tag] = "$tag";
		$this->_urls[$tag] = "$url";
	}

	function css()
	{
		$css = "#htmltagcloud { text-align:  center; line-height: 1; }\n";
		for ($l=0; $l<$this->__level; $l++)
		{
			$font = 11 + $l;
			$css .= "span.tagcloud$level { font-size: ${font}px;}\n";
			$css .= "span.tagcloud$level a {text-decoration: none;}\n";
		}
		return $css;
	}

	function calclevel()
	{
		//sort($this->_counts);

		$max = log(max($this->_counts));
		$min = log(min($this->_counts));
		$factor = 0;;

		// special case all tags having the same count
		if ($max - $min == 0)
		{
			$min = $min - $this->__level;
			$factor = 1;
		}
		else
		{
			$factor = $this->__level / ($max - $min);
		}

		if (count($this->_counts) < $this->__level )
		{
			$factor *= count($this->_counts)/$this->__level;
		}

		foreach ($this->_counts as $key => $count)
		{
			$this->_levels[$key] = (int)((log($this->_counts[$key]) - $min) * $factor);
		}
	}

	function html()
	{
		$ntags = count($this->_tags);
		if ($ntags <= 0)
		{
			return "<div id='htmltagcloud'>Nothing to do</div>";
		}
		$this->calclevel();
		sort($this->_tags);
		$html = "";
		foreach (($this->_tags) as  $key => $tag)
		{
			$html .=  " <span class=\"tagcloud".$this->_levels[$tag].
					"\"><a href=\"".urldecode($this->_urls[$tag]).
					"\" title=\"".$this->_counts[$tag].
					"\">".$tag."</a></span> ";
		}
		return "<div id='htmltagcloud'>$html</div>";
	}

	function html_and_css()
	{
		$html = "<style type=\"text/css\">" . $this->css() . "</style>";
		$html .= $this->html();
		return $html;
	}

}

?>
  • Share/Bookmark
Dec
30
2009

Database migration: MS Access to MySQL server

The Problem
Recently I solved a database migration problem: migrate MS Access database encoded in GB2312 to MySQL server encoded in UTF-8. I’d like to share what I did and hope it is useful to help you solve your problem.

I had a lot of useful data in an MS Access database. They were collected through ASP Gallery 1.0, which was run on Windows IIS web server. I did not have an IIS server to run ASP Gallery for a long time and do not have a plan to launch an IIS server in the coming future.

I wrote simple PERL CGI’s and used it from 2007 to 2008. Now I have a powerful Apache2 server and I developed an powerful PHP web application. In order to use the useful information in the MS Access database, I have to migrate all data to MySQL server.

The Solution
There is a big problem in front of me. All data in the MS Access database was encoded in GB2312. My MySQL server and everything else related to the new web server use UTF-8 encoding. I have to convert the GB2312 encoding to UTF-8 encoding. That was solved easily. See the corresponding function in migrate.php.

First I used the MySQL migrate tool (you can download it from mysql.com website) to transfer data (migrate_class) to MySQL server. Then I wrote a nice PHP application called migrate.php, that help me to merge the data from the table to MySQL server (category) table in donghome database.

The PHP code

<?php
// database-specific information
DEFINE(DB_USER,"your username");
DEFINE(DB_PASSWORD,"your password");
DEFINE(DB_HOST,"your mysql server host");
DEFINE(DB_NAME,"gmain");

// connect to mysql
$db_connection = mysql_connect(DB_HOST,DB_USER,DB_PASSWORD);

// select the database
mysql_select_db(DB_NAME);

// process gmain database that includes old gallery data tables

//update_class_table();

//migrate_class();

function migrate_class()
{
	$sql = "SELECT classid, pclassid, title FROM class";
	$query_result = mysql_query($sql);
	$counter = 0;
	while ($row = mysql_fetch_array($query_result, MYSQL_NUM))
	{
		$classid=$row[0];
		$pClassID = $row[1];
		$name = $row[2];
		$counter ++;
		echo $counter. " : ";
		update_category($classid, $pClassID, $name);
	}

}
function update_category($classid, $pClassID, $name)
{
	$sql1 = "INSERT INTO donghome.category (id_category,parent_id,name) ".
			"VALUES ($classid,$pClassID,'".mysql_escape_string($name)."');";
	echo $sql1."<br>";
	mysql_query($sql1);
}

function update_class_table()
{
	$sql = "SELECT * FROM migrate_class";
	$query_result = mysql_query($sql);
	$str = "all classes in the table <br>";
	$str .= "ClassID,directory,pClassID,title,hyperlink,hasdir,user,path<br>";
	while ($row = mysql_fetch_array($query_result, MYSQL_NUM))
	{
		$path = "";
		$classid=$row[0];
		$directory = $row[1];
		$pClassID = $row[2];
		$title = $row[3];
		$hyperlink = $row[4];
		$hasdir = $row[5];
		if ($row[5])
		{
			$path = buildpath($directory,$pClassID);
		}
		$str .= "*** $row[0],$row[1],$row[2],".convertGB_UTF8($title).",$row[4],$row[5],$row[6],$path<br>";
		updateClass($classid,$directory,$pClassID,$title, $hyperlink, $hasdir, $path);
	}
	echo $str;
}

function updateClass($classid,$directory,$pClassID,$title, $hyperlink, $hasdir, $path)
{
	$sql1 = "INSERT INTO class (classid,directory,pclassid,title,hyperlink,hasdir,path) ".
			"VALUES ($classid,'$directory',$pClassID,'".mysql_escape_string(convertGB_UTF8($title))."', '$hyperlink', $hasdir, '$path');";
	echo $sql1."<br>";
	mysql_query($sql1);
}

function buildpath($path,$parentdir)
{
	$apath = $path;
	$sql = "SELECT * FROM migrate_class WHERE ClassId = $parentdir;";
	$query_result = mysql_query($sql);
	$row = mysql_fetch_array($query_result, MYSQL_NUM);
    if ($row[5])
	{
		$apath = $row[1]."/".$apath;
	}
    $aparentdir = $row[2];
	if ($aparentdir != 0)
	{
		$apath = buildpath($apath,$aparentdir);
	}
	return $apath;
}

function convertGB_UTF8($str)
{
	$str = mb_convert_encoding($str, "UTF-8", "GB2312");
	return $str;
}

?>
  • Share/Bookmark
Dec
23
2009

Fix network configuration problem

The problem
I have a couple of computers with identical hardware configuration. I used one of them to install Ubuntu server to new hard drives. After I completed the preparation of all hard drives and installed the m to other machines. The problem came. Everything works fine except the network. eth0 has problem.

The solution

This solution is come from a post. I forget the address.

First, the diagnosis was that ifconfig would not show eth0 at all. lspci and dmesg reported no errors, really, and obviously modprobe was useless. ifup reported some strange errors like:

SIOCSIFADDR: No such device eth0
eth0: ERROR while getting interface flags: No such device

Google didn’t find anything useful on any search, until I came across this dude’s blog who was getting an identical error in a totally different situation.

http://www.pletscher.org/blog/?p=29

WOOHOO!

I ran ‘ifconfig -a’ and it found an eth1 for some reason (though ‘ifup eth1′ also had no effect) which had a MAC address in it. I hopped into ‘/etc/iftab’, changed the MAC address on eth0 to the MAC that was attached to eth1 in ifconfig and rebooted. VOILA! Network up and running!

Hope this helps someone.

  • Share/Bookmark
Dec
23
2009

VBA function for multiple comparison

In SAS, lsmeans treatment /pdiff of PROC mixed or GLM output mean values and a matrix of probability values of all pair wise comparison. However, we have to create the traditional comparison table by ourselves. In order to automate the process, I developed a VBA function to do the job. The source code is the following. There are three parameters as the input of the function. The first one is a column vector. The second parameter is a square matrix that includes probability values of all pairwise comparison. The third one is optional, it is the significant level, with a default value of 0.05. The results will be a column vector with a equal length of the input mean vector. If you do not know how to use vector and matrix in Excel, please look at Excel help and learn it. It is very useful when you work with array, matrix, and vector. The basic operation is select continuous cells of a column or a row and enter a formula and then press down SHIFT key and ENTER key at same time. In this way, we are working with a function that operate a vector or a matrix.

Option Explicit
Option Base 1

Function MultComp (subIndex As Object, Pmatrix As Object, dptional alpha As Double = 0.05)
	Dim myresult ( )
	Dim NumSub As Integer
	Dim Subj ectl, Subj ect2, pValue
	NumSub = UBound(subIndex(), 1) - LBound(subIndex(), 1) + 1
	Dim Px, Py
	Px = UBound(Pmatrix(), 1) - LBound(Pmatrix(), 1) + 1
	Py = UBound(Pmatrix() , 2) - LBound(Pmatrix ( ) , 2) + 1
	If Px <> Py Then
		MsgBox "The matrix is not synmatric"
		Exit Function
	End If
	If Px <> NumSub + 1 Then
		MsgBox "The size of matrix is not compatible with the number of subjects"
		Exit Function
	End If

	'Do comparison
	Dim i, j, k, l, startletter
	ReDim myresult (NumSub, 1)
	For i = 1 To NumSub
		myresult (i, 1) = ""
	Next
	k = 1
	i  = 1
	If alpha <= 0.01 Then startletter = 64 Else startletter = 96
	While (i <= NumSub)
		If i = 1 Then myresult(1, 1) = myresult(1, 1) & Chr(start1etter + k)
		Subject1 = subIndex (i)
		For l = i - 1 To 1 Step -1
		        Subject2 = subIndex (l)
		        pValue = Val (Pmatrix(Subject1 + 1, Subject2 + 1) )
		        If pValue <= alpha Then
			        Exit For
		        Else
			        myresult (l, 1) = myresult (l, 1) & Chr (startletter + k)
		        End If
		Next
		For j = i  + 1 To NumSub
			Subject2 = subIndex ( j )
			pValue = Val (Pmatrix(Subject1 + 1, Subject2 + 1) )
			If pValue <= alpha Then
				k = k + 1
				myresult (j, 1) = myresult (j, 1) & Chr (startletter + k)
				i = j - 1
				Exit For
			Else
				myresult (j, 1) = myresult (j, 1) & Chr (startletter + k)
				If j = NumSub Then i = j + 1
			End If
		Next
		i = i + 1
	Wend
	MultComp = myresult
End Function

Tip for the function: In this function, we use matrix and vectors. The returned result is in an column vector. In the function we have to declare a two dimension array with the second index as 1. If the returned vector is in a row, we only need to declare a one dimension array. If a function returns a matrix, you have to declare a two dimension array, like dim res(x,y).

  • Share/Bookmark
Dec
5
2009

Useful applications for Windows Mobile 6.1

Recently I upgraded my Verizon Wireless mobile phone to Windows Mobile Smartphone XV6800. I like it very much because I can do a lot of things on it. The most useful function of this phone is accessing WiFi hotspot. Here I’d like to summarize how I configure it to connect to my home WLAN, access LAN resources, dial international calls through Skype and so on.

Connect your windows mobile phone to home WLAN

This section is from someone’s post. I googled the internet to search for solution. I came across this nice post and followed the instruction to get my phone works. Two bad I lost the web link.

In order to set-up a local area network between a computer and a PDA there are two phases to follow. I’ve tested the solution on a “server” laptop running both Vista and Windows XP, and on a PDA “client” under Windows Mobile 6.1. We can set-up as many clients as we want, whether PDAs or computers. In addition, this implementation is on WiFi without even using a WiFi router/access point.

Phase 1 – set-up network and its’ “server” (computer):
- Make sure the computer’s WiFi card is enabled.
- Do the WiFi network set-up as per http://www.youtube.com/watch?v=ndYUkSdCQ3Q&NR=1. The video shows a Windows XP case but I’ve also done it on Vista. You need to enter the network’s SSID and remember it. Also you need to write-down the computer’s name (Computer_name) from the System Tools/System Information.
- Choose/create a directory (Shared_directory) with property set to public access. If the directory is not right under C:\, then make sure the whole path tree has the access type property set to public.
- Go under network connections, right click on our network name and set the IPV4 address to 192.168.1.1. This computer will serve as hub for all the clients attached to this network.

Phase 2 – set-up the PDA client (under Windows Mobile 6.1):
- Make sure the WiFi card is enabled.
- Go under WiFi connections and choose to show “only access points” networks. You should see the network with the SSID you entered on the “server”.
- Go under network cards, choose “the right one” (that depends of the PDA manufacturer). In my case I had one marked “WLAN”. Set the IP address static (ex: 192.168.1.10), with gateway set to 192.168.1.1 and mask 255.255.255.0 (automatically filled-in). At this moment you’ll see on the computer the name of the PDA as part of the SSID-named network.
- Go under Explorer (always on the PDA), then Manu/Browse/Open a path/New location and in the field enter \\Computer_name\ Shared_directory.

Use SKYPE to call people worldwide

Visit http://skype.com once your home WLAN works. Download the right version of the skype to your cell phone. Usually select Skype for Windows Mobile, the current version is Skype 3.0 for Windows® Phones. You can switch to Chinese interface once Skype is successfully installed.

Read/Write Chinese characters in your Windows phone

There is a really good Windows Mobile App that provide Chinese support in your Windows Mobile devices: CE-Star for WM5 and WM6.x. The developer, Mobem Technologies Inc.(http://www.mobem.com), based in Beijing, claims that CE-Star for WM5/6 is the only true localizer for Windows Mobile 5.0/6.x devices in the world. It comes with our invention DynaNLS technology to enable your WM5/WM6 device to view and write Chinese and Japanese in all applications. The latest 2.8 R3c has better WM6.1 and Japanese support. And 2.8 R3c now has better support for high resolution devices.

PuTTY for Windows Mobile

There is a Windows Mobile port of famous PuTTY, a SSH client, available at http://www.pocketputty.net/. You can download the software directly to your Windows Phone and unzip the file. The execuatable is ready to use. You may have difficulty to get through the first screen because there is pupup dialog window to ask your permission to continue. Once you ge through this screen, everything goes smoothly. The only thing I do not like is that its font size is really small. I can barely see the text. But it is ok if you only do a little bit things on it.

  • Share/Bookmark