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
Nov
30
2009

A good website for text translation between English and Chinese

Recently there is a need to translate some English documents to Chinese. Since the documents are long and also with some unfamiliar words, I need to look up dictionary to translate the documents. It is tedious and time-consuming. One of my friends sent me a link (http://us.mdbg.net/chindict/chindict.php?page=translate) that point to a online translation. After I evaluates the translation back and forth, I found that it does a good job. I decided to use the site to do the initial translation and then modify it to make the translation final. The following is the Chinese translation of this paragraph.

最近有需要翻译一些英文文件中。由于文件很长,也存在一些不熟悉的话,我需要查字典翻译的文件。这是繁琐和费时。我的一个朋友给我一个链接(http://us。mdbg。网/ chindict / chindict。PHP的?页=翻译)是指向一个网上翻译。在我的翻译评估来回,我发现它做得很好。我决定使用这个网站做初步翻译,然后对其进行修改,使翻译决赛。以下是本款的中文译本。

Based on my personal view, this is very good. What I need to do is change the order of the words and make the sentences more smooth and fluent. It can same me a lot of time.  The following Chinese translation was from Google Translate (http://translate.google.com/).

最近有需要翻译一些英文文件中。由于文件很长,也存在一些不熟悉的话,我需要查字典翻译的文件。这是繁琐和费时。我的一个朋友给我一个链接(http://us.mdbg.net/chindict/chindict.php?page=translate)的指向网上翻译。在我的翻译评估来回,我发现它做得很好。我决定使用这个网站做初步翻译,然后对其进行修改,使翻译决赛。以下是本款的中文译本。

I can hardly find difference between the two versions of Chinese translation. So you can use either one to do the initial translation. To be aware that both websites can do translation in another way around, that is, from Chinese to English.

Here is an example. The following paragraph is original Chinese paragraph.

美国经济尚未完全走出阴影,政府现在感到巨大的压力,首要任务是增加美国人的就业职位,可是如何增加就业呢?目前还没有一个最好的方法。

English translation from Google Translate:

U.S. economy is not completely out of the shadows, the Government now feel great pressure, first and foremost task is to increase American jobs, but how to increase employment? There is no one best way.

English translation from MDBG.net:

US economy is not completely out of the shadows, the Government now feel great pressure, first and foremost task is to increase American jobs, but how to increase employment? There is no one best way.

To me, the two versions of translation are same. I will use either one to do the initial job. Thank for the technology advancing, now we can save hours to complete the tedious translation from one language to another.

  • Share/Bookmark
Nov
26
2009

Display stock charts on your own website

Plain stock chart
In searching an easy way to display stock charts on a web page hosted in a web server, two useful scripts were found on the internet:

1. Easy Yahoo stock chart ASP.NET Page
2. Displaying a daily chart for a ticker symbol

Even the scripts were written in different languages, they use a common idea that fetch the Yahoo stock charts and display them locally. The first article gives a basic framework to do this in PHP. It has one missing statements at the beginning of the script. I added that and use the Yahoo link from the second article. Now this script can show 6 months and 3 months and daily chart at once.

<?php
//stock chart shower
//Beginners PHP
//Description : This allows a user to enter a ticker symbol
//and rather than the usual dry quotes displays a chart of
//how the stock has performed over the whole year

$symbol=$_POST['symbol'];

if ($symbol =="")
{
?>
<html><body>
<form action='<?php print $PHP_SELF; ?>' method ='post'>
Enter your ticker symbol :<input type='text' name='symbol' size = 6><br>
<input type='submit' value="show chart">
</form>
</body></html>
<?php
}
else
{
?>
<html>
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="image/gif; charset=iso-8859-1">
</head>
<img border="0" src="http://ichart.finance.yahoo.com/z?s=<?php print $symbol; ?>&t=6m&q=c&l=on&z=l&a=v&p=s">
<img border="0" src="http://ichart.finance.yahoo.com/z?s=<?php print $symbol; ?>&t=3m&q=c&l=on&z=m&a=v&p=s">
<img border="0" src="http://ichart.yahoo.com/t?s=<?php print $symbol; ?>">

</body>
</html>
<?php
}
?>

Flash Stock Chart

Open Flash Chart 2 provides a whole library of PHP, PERL, Python, .NET and more languages that help your generate SWF flash charts for free. On its website, there are tons of examples to help you use the library. OFC2 uses JSON as the file format and you can generate cool chart in very short time.

The PHP source code to get data from database and generate JSON file for SWF chart is listed here.

<?php

include_once 'php-ofc-library/open-flash-chart.php';
include_once '../stocks_secureinfo.inc';

$stock_tick = 'LIWA';

$sql = " SELECT price_open, price_high, price_low, price_close, stock_volume, c_year, c_month, c_day from stockdata s ".
" INNER JOIN company c ON s.id_company=c.id_company ".
" INNER JOIN caldate d ON s.id_caldate=d.id_caldate ".
" WHERE c.tick='$stock_tick' ".
" ORDER BY c_year ASC, c_month ASC, c_day ASC ".
" ; ";
$result = mysql_query($sql);

if (!$result) {
die('Invalid query: ' . mysql_error());
}

$data = array();
$volume = array();
$max = 0;
while($row = mysql_fetch_array($result))
{
//
// LOOK: PHP thinks our data is text,
//       force it to be an integer:
//
$data[] = new candle_value(
(float)$row['price_high'],
(float)$row['price_open'],
(float)$row['price_close'],
(float)$row['price_low']);

$volume[] = (float)$row['stock_volume'];

}

$title = new title( $stock_tick );

### Candle graph for stock price
$candle = new candle('#9933CC');
$candle->set_values($data);
$candle->set_tooltip('#x_label#<br>High: #high#<br>Open: #open#<br>Close: #close#<br>Low: #low#');
//$candle->set_on_show(new bar_on_show('drop', .9, 0));

$y = new y_axis();
$y->set_range( 0, 11, 0);

$chart = new open_flash_chart();
$chart->set_title( $title );
$chart->add_element( $candle );
$chart->set_y_axis( $y );

### bar graph for stock volume
$bar = new bar();
$bar->set_values( $volume );
$bar->axis = 'right';

$yr = new y_axis_right();
$yr->set_range( 0, 2000000, 0);

$chart->add_element( $bar );
$chart->set_y_axis_right( $yr );

#echo $chart->toPrettyString();
write2file($chart->toPrettyString(),$stock_tick."_price.json");

function write2file($str,$filename)
{
$fh = fopen($filename, 'w') or die("can't open file");
fwrite($fh, $str);
fclose($fh);
}

?>

The HTML file that used to show the SWF chart is listed below.

<html>
<head>

<script type="text/javascript" src="js/swfobject.js"></script>
<script type="text/javascript">

swfobject.embedSWF(
"open-flash-chart.swf", "my_price_chart",
"1000", "400", "9.0.0", "expressInstall.swf",
{"data-file":"LIWA_price.json"} );

</script>

</head>
<body>

<h1>Hello world!</h1>
<div id="my_price_chart"></div>
<br>
<div id="my_volume_chart"></div>
</body>
</html>

For details to use OFC2 and the above codes, please go to OFC2 website and read more details.

Weekly Chart from StockCharts
StockCharts provides nice stock charts with some useful information. A strategy similar to get charts from Yahoo site can be adopted. The link to point to stock chart looks like http://stockcharts.com/c-sc/sc?s=ARST&p=W&b=5&g=0&i=t05444095590&r=6408. There is a problem when you directly embed the link to your website. It suggests you visit their site to view the chart instead of just show it. To solve the problem, we can download the stock charts locally and save them to PNG files. Then the charts can be used as local images. To do that, we can use Linux wget command.

wget “http://stockcharts.com/c-sc/sc?s=ARST&p=W&b=5&g=0&i=t05444095590&r=6408″ -O arst.png

  • Share/Bookmark