Archive for the ‘Php Talk’ Category.

QuickForm and AutoSuggest

The best example of auttosuggest filed I can instantly think of is Google. While designing dynamic forms I felt the requirement of such field. As I mostly use PEAR class and HTML Quickform to design dynamic forms in php. However in HTML Quickform there is autocomplete type but still there is no support for autosuggest. I googled a lot to get such support, but found it out in RFC of HTML Quickform. So I started working upon it. My first job was to found out a autosuggest Javascript code suitable for integration. I searched out an autocomplete javascript code by Beau D. Scott

The reasons why I selected Beau’s code is :
The code is simple to use but robust and has good documentation.
It uses standard JS library like prototype and scriptaculous.

Now having previous knowledge of integration of QuickForm and Jscalender I created the code for autosuggest class. This autosuggest class file contains constructor function, toHtml function which generates the HTML code for the field, getFrozenHtml function to return the autosuggest content in HTML and finally the registering process of the autosuggest type with HTML QuickForm. I put this autosuggest class name as autosuggestwce. View this wceautosuggest.php file.

To use this autosuggest field in HTML Quickform you need to have 3 javascript files as prototype.js, scriptaculous.js and autocomplete.js. Prototype Javascript is used for javascript framework, Scriptaculous for show and hide effect and AutoComplete is the main javascript functionality file. Among them scriptaculous.js can be removed if you don’t like to show effects, but you need to modify certain section in the wceautosuggest.php file. You also need to declare $GLOBALS['_HTML_QUICKFORM_AUTOSUGGEST_BASEPATH'] the global path defining variable for the javascript files path in the page where you will generate the form.

This autosuggest uses php script to populate values. The name of the php script has to be mentioned in the $attribute array for the key ‘fileref’.

If you are using DB_Table here is snippet of code

'user_name' => array(
'type' => 'varchar',
'size' => 255,
'qf_type' => 'autosuggestwce',
'qf_label'=> 'UserName:',
'require' => false,
'qf_attrs' => array(
'id' => 'user_name_autosuggest',
'autocomplete' => 'off',
'fileref' => 'getusersname.php',
),
),

If you are using QuickForm directly then here is the code snippet

$form = new HTML_QuickForm('someTest', 'get');
$form->addElement('autosuggestwce', 'username', 'UserName:', "array('id' => 'user_name_autosuggest', 'autocomplete' => 'off', 'fileref' => 'getusersname.php')");
$form->display();

Here is the code segment of php script

<?php
$UsrObj = new CLUsrChk($DBObj, 'hllqz_tblusers');
$SqlStatement = "SLECT user_name FROM ".$UsrObj->table." WHERE user_name LIKE ('".$_GET['s']."%')";
$UsrNameArray = $UsrObj->bd->query($SqlStatement);
echo json_encode($UsrNameArray);
?>

Here is the screenshot

autosuggest_field
autosuggest_filed_populated

However if you require the files for your reference please let me about that.

I was planning to do this post almost a month ago but I was busy with learning another Javascript framework jQuery. I am started loving it. Hope I will be able to post something about jQuery in near future.

Web site hacked via HTACCESS

Here is another example how your site got hacked. I found this instance very recently in Godaddy server. This type of site hacking is not very common. You may not be able to detect any specific web page infected if you search your site using Google Diagonestic tool for safe browsing mentioned in my earlier post – Iframe code injection. In this kind of attack none of your web pages get infected but your .htaccess file gets modified and becomes the main source of redirection to malware containing site. Let me show you an infected .htaccess file for example. 

hacked_htaccess

Modified HTACCESS file used for hacking

Experienced developer can understand why this is so dangerous. Let me explain a little for the newbies. In case of apache web server configuration directives are described in httpd.conf file. Many cases this file can’t be accessed or modified due to security reasons. So to change some configuration directives for a specific website or its sub directory best solution is to use .htaccess file. To know further about .htaccess file and its functionality you can read .htaccess files. However URL rewriting, URL redirection, authentication are the important functionality .htaccess file are used for.

In the example htaccess file there are 3 sections. First line is for instructing the apache web server to put the rewrite engine on. This is first section. Second section goes from line no. 2 to line no. 8. This section is basically for condition checking on URL. Its checking if the visitors are coming from a website or page with URL containing the following words like google, aol, msn, yahoo, yandex, rambler or ya. NC means pattern checking will be case insensitive. OR means combines with other rule. Third section is in line no. 9. It says if any of the above pattern checking become true then it will redirect to the specified URL. Here R means redirection. Normally this generates HTTP response code 302 means moved temporarily. L means this is the last rule.

So the result is that if some visitor coming to the site from above specified search engine, they will be simply redirected to the malware site without understanding whats happening. So be careful if you come to know your site gotta hacked and youre unable to find out why then take a look at your .htaccess file.

Iframe code injection

After a long days I am back for blog post. Last one month I was very much irritated with the problem occurred in some of my client website. In a Sunday morning while I was sleeping one of my client ranged me and asked me to check her website as she got a mail from google that her website is spreading malware. I got confused as I had never faced this kind of problem. I started checking the website. But the antivirus in my Laptop didn’t allowed me to open the site at all. Then I decided to go to my office to check the situation.

In my office I checked the site thoroughly(OMG, I was able to open the site in my office). I found iframe code with hidden visibility was inserted in some pages. To be more specific index pages. I checked all the index pages in office PC, deleted the infected pages in the server and uploaded the pages from PC. Checked, cleaned all the html, php, temporary files. Almost near about afternoon I was back to my home while thinking how this happened.

Iframe Injected

Iframe Injected

Next Morning after arriving in the office I started checking the website and I found it was again infected by the hidden iframe. Site url was different as earler it was .cn and next day it was .ru I was upset about how to fix the things. Believe me or not in the last one month this site got infected 27 times. Our team had experienced the same attack for 5 more site. It was a horrible experience for us.

We had done lot of googleing to find out the preventive measurement. We found out lots of information regarding this. Some of them are good and some of them are misleading too. So here I like to point out some effective ones only.

  1. You should have good antivirus installed in your system from where you access web. I am using avast free edition and it works fine for me.
  2. Please check your websites on a regular basis. If you see if any web page with a blank section in the top them be almost sure that it is infected. Your antivirus should give you warning.
  3. If you find any of your website get infected then start following the next steps.
  4. First of all scan your machine with the antivirus. A boot time scan is more preferable.
  5. Replace all the pages in the website using a local copy from your system. If the web site is too big to repalce then try to repalce all the pages with name index. Then check the site again.
  6. Once the site is cleaned change the ftp details for the site and if possible do the same for the other sites whose details are kept in your ftp application.
  7. Keep checking the site in a short span of interval.

You should also check your site in google too. If google find out some problem with your site they may have shown a warning message like “This site may harm your computer”. Another way to check your site is

http://www.google.com/safebrowsing/diagnostic?site=http://www.yourdomain.tld

If you find that google is showing the warning message for your site you can request Google for a recheck via Google Webmaster Tool. But you should check the site twice after cleaning and then request for review.

However I have designed a code in php for checking mainly the index pages in the website. Here is the code.

<?php
// page-checker.php
$path = ".";
$baseDir = basename(dirname($_SERVER['PHP_SELF']));
$WebPath = 'http://'.$_SERVER['HTTP_HOST'].'/'.$baseDir;
$content_pattern = "iframe";
echo "Checking files for IFRAME Infection<br/>";
$dir_handle = @opendir($path) or die("Unable to open $path");
echo "Directory Structure of $WebPath<br/>";
navigate($dir_handle, $path, '');
function navigate($dir_handle,$path, $WebPth)
{
global $WebPath, $content_pattern;
echo "<ul>";
while (false !== ($file = readdir($dir_handle)))
{
$dir = $path.'/'.$file;
if(is_dir($dir) && $file != '.' && $file !='..' )
{
$handle = @opendir($dir) or die("undable to open file $file");
$WebRef = $file.'/';
navigate($handle, $dir, $WebRef);
}
elseif($file != '.' && $file !='..')
{
if(preg_match('/^index+/',$file))
{
$ChcekFlag = FALSE;
echo "<li>";
echo "<a href='".$WebPath.$WebPth.$file."'>".$WebPth.$file."</a><br />";
$handle = @fopen($dir, "r");
if ($handle)
{
while (!feof($handle))
{
$content = fgets($handle);
if(stristr($content, $content_pattern))
{
$test = stristr($content, $content_pattern);
echo $test."<br />";
$ChcekFlag = TRUE;
}
}
}
fclose($handle);
if($ChcekFlag)
{
echo "<font color='red'>Infected</font><br />";
}
else
{
echo "<font color='green'>Clean</font><br />";
}
echo "</li>";
}
}
}
echo "</ul>";
}
?>

you can put this code in the root level of your website (in www or public_html or httpdocs). Browsing this page will show all the index pages with status of it.

Current I am working upon extending the code so that it can clean the infected pages automatically. Hopefully I will post it within few days.

Picasa web album slideshow – Development guide

I was looking for a application to embed slideshow using pictures from picase web album. I found some plugins which can be used in blog or myspace. Some of them uses the picasa slide show url opened in a iframe or div. Then you will have less control on the slideshow as it is controlled by the slideshow application of picasa. But I required more control on the images from picasa.

I was looking for some application which will fetch/store all the images for an album in picasa and create a slideshow with more control on the images. I found nothing thats suites my requirement. So I started to design an application of such kind. On the basis of functionality I sub devided it into two major part. First is fetch the image related information for an album and store it if required. Second is display the slideshow using those image information.

In picasa you can view the pictures as set or individual but you won’t get actual picture name or its location. So I found now simple way to get the pictures name and their location. While searching more for such option I found there is a RSS feed for each album. The RSS feed provides image names and its location details. It makes my job easier. Now objective became to process the RSS feed to get the image related information. For this purpose I used XML-RSS package from PEAR. Here is snapshot of the code I wrote to process the feed:


<?php
require_once "XML/RSS.php";
//$FeedURL is the URL of the rss feed of an album in picasa
$FeedURL = "http://picasaweb.google.com/data/feed/base/user/wce/albumid/5331321673727336541?alt=rss&kind=photo&hl=en_GB";
$rss =& new XML_RSS($FeedURL);
$rss->parse();
$rssArray = $rss->getStructure();
$PicasaDataArray = array();
$InfoArray = array();
for($C=0; $C<count($rssArray); $C++)
{
if($rssArray[$C]['type'] == 'item')
{
$PicasaDataArray[] = array(
'title' => $rssArray[$C]['title'],
'image' => $rssArray[$C]['enclosures'][0]['url'],
'link' => $rssArray[$C]['link'],
'description' => $rssArray[$C]['description'],
);
}
elseif($rssArray[$C]['type'] == 'image')
{
$AlbumTitle = $rssArray[$C]['title'];
$AlbumPicture = $rssArray[$C]['url'];
$CreateDate = $MetaInfo['lastbuilddate'];
}
}
// this $PicasaDataArray contains all the picture related information of an album from picasa web.
?>

Now this $PicasaDataArray can be stored in files/database or can be directly used for the slideshow. While processing the feed by this I found the feed contain other information like title, description, link of the album, its last build date etc. So I modified the code a little more to store these information too. So the first part of my application is complete.

Now the second part – slideshow using $PicasaDataArray. For this section I didn’t tried to put my head to develop slide show application as I had already seen some very nice attractive slideshow application. They are also easy to use and configure. One of my favourite is Lightbox JS. Another good slideshow script is Highslide. Both of them are very nice and easy to configure. So I used one of them for my purpose. Here is another snapshot of code


<?php
require_once "XML/RSS.php";
//$FeedURL is the URL of the rss feed of an album in picasa
$FeedURL = "http://picasaweb.google.com/data/feed/base/user/wce/albumid/5331321673727336541?alt=rss&kind=photo&hl=en_GB";
$rss =& new XML_RSS($FeedURL);
$rss->parse();
$rssArray = $rss->getStructure();
$PicasaDataArray = array();
$InfoArray = array();
for($C=0; $C<count($rssArray); $C++)
{
if($rssArray[$C]['type'] == 'item')
{
$PicasaDataArray[] = array(
'title' => $rssArray[$C]['title'],
'image' => $rssArray[$C]['enclosures'][0]['url'],
'link' => $rssArray[$C]['link'],
'description' => $rssArray[$C]['description'],
);
}
elseif($rssArray[$C]['type'] == 'image')
{
$AlbumTitle = $rssArray[$C]['title'];
$AlbumPicture = $rssArray[$C]['url'];
$CreateDate = $MetaInfo['lastbuilddate'];
}
}
?>
<html>
<head>
<title>Slide Show :: <?php echo $AlbumTitle;?></title>
<script type="text/javascript" src="js/prototype.js"></script>
<script type="text/javascript" src="js/scriptaculous.js?load=effects,builder"></script>
<script type="text/javascript" src="js/lightbox.js"></script>
<link rel="stylesheet" href="css/lightbox.css" type="text/css" media="screen" />
</head>
<body>
<a href="<?php echo $AlbumPicture;?>" rel="lightbox[picasa]"><img src="<?php echo $AlbumPicture;?>" /></a>
<div style="display:box;">
<?php
foreach($PicasaDataArray as $ImageInfo)
{
echo '<a href="'.$ImageInfo['image'].'"' rel="lightbox[picasa]">'.$ImageInfo['title'].'</a><br> ';
}
?>
</div>
</body>
</html>

I made this code simple and easy to use. Though I have used xml-rss class from pear but it can be repalced by and standard xml-rss parser class. Experienced developer can modify this code or enhance its feature much more as per their requirement. If like to use this code or if you have any suggestion let me know about it via your comment.

Converting Excel date/time to Unix timestamp

Timestamp conversion are required when you import information generated by Windows based application to UNIX system. I faced a similar type of problem when I was trying to read data from a MS Excel file and storing it in MySQL database using a php code.

I was using Excel_reader class to read the Excel file. In that file there were two columns for 2 dates. While reading those column value I found they contain some numeric value. Those values are not same as unix timestamp value. As I was trying to store those values as timestamp I need to convert them into the timestamp.

After some searching and reading from internet I found that Windows and Unix system stores timestamp in different manner. Once this is clear to me I have converted them easily. So let us understand how these two system stores timestamp .

In Unix system timestamp is stored as integer in terms of seconds. If we consider the current timestamp value in Unix then it is basically the no. of seconds passed from 1 January 1970 00.00Hrs to till now. One important thing for Unix timestamp is that it is measured with reference to GMT time. That means there is no time-zone adjustment considered in case of Unix timestamp.

In case of Windows time it is stored as floating point/real number but in terms of days. For current timestamp, the no. days spent from 1 January 1900 stored in integer part and fraction of the day stored in the fractional part of the timestamp.

Now comes the conversion process. I made a simple conversion calculation as follows:


$DayDifference = 25569; //Day difference between 1 January 1900 to 1 January 1970
$Day2Seconds = 86400; // no. of seconds in a day
$ExcelTime //integer value stored in the Excel column
$UnixTime = ($ExcelTime - $DayDifference)*$Day2Seconds;

Now if you look at the calculation, you may find that the conversion is not absolutely accurate. This is because I haven’t consider the fractional part of the Excel time. The reason behind doing so is that all I need to do is to convert a date from Windows format to Unix format. So fraction part of windows time won’t affect a lot for my requirement. But if you use this calculation for converting a date-time from Windows format to Unix format then conversion of the fractional part should done.
If you like this small tips please let me know about it.

QuickForm and Jscalendar

Most of us are familiar with calendars in web pages. Small calendar showing date and year are really good to see and useful too. While in case of forms we have seen calendars attached with date fields. In some of my earlier projects I have designed date fields using simple drop down menu containing the data, month and year menu. It’s good but not very user friendly as user need to select 3 menus to choose a certain date. I had to stick with that format as I mostly use PEAR HTML_QuickForm to design forms in the web pages. Among many reasons the most unavoidable one is that it automatically generates client side validation JavaScript code. With time I realized that I should find some options to integrate calendar object with the QuickForm.

After giving a thorough search I selected jscalendar to incorporate with my form elements. The reasons behind selecting jscalendar are:

  • It has a nice interface and wide variety of themes.
  • Multiple integration options along with selectable date format to put the date in the text field.
  • Support for integrating the calendar object with HTML_QuickForm.

Prior to integrate the jscalendar I need to upgrade HTML_QuickFom version to 3.2.10 as I found some code added in this version to support jscalendar. I also need to upgrade my PEAR DB package to version 1.7.13 and DB_Table to version 1.5.5. In my projects most of the cases I generate forms using DB_Table instead of using QuickForm directly. This gives an extra benefit for data validation and storing them in database.

After the up-gradating the required pear packages I worked upon integrating the jscalendar code. After a spending a moderate amount of time I was able to work jscalender with the QuickForm. But unfortunately when I was trying generate forms using DB_Table jscalendar component was not working. I was getting javascript errors.
I was following the method described by Philippe Jausions of 11abacus in jscalendar.php file. It was working fine with the QuickForm. In that case I was using addElements function to add jscalendar with proper options using the $option array like this –


$options = array(
'baseURL' => '../js/jscalendar/',
'styleCss' => 'calendar-win2k-1.css',
'language' => 'en',
'button' => '',
'setup' => array(
'inputField' => 'datefield1',
'ifFormat' => '%d.%m.%Y %H:%M',
'showsTime' => true,
'time24' => true,
'weekNumbers' => false,
'showOthers' => true
),
);
$form->addElement('jscalendar', ' datefield1', 'My Date', $options);

I used this same option array in the column definition for the same field, as DB_Table uses the column definition for the attributes of the form elements of the form. I written like


'datefield1' => array(
'type' => 'varchar',
'size' => 20,
'qf_type' => 'jscalendar',
'qf_label'=> '<span class="caption">Date:</span>',
'require' => false,
'qf_attrs' => array('class'=> 'formfield','id' => 'datefield1'),
'qf_opts' => array(
'baseURL' => '../js/jscalendar/',
'styleCss' => 'calendar-win2k-1.css',
'language' => 'en',
'button' => '',
'setup' => array(
'inputField' => 'listadata',
'ifFormat' => '%d.%m.%Y %H:%M',
'showsTime' => true,
'time24' => true,
'weekNumbers' => false,
'showOthers' => true
),
),
'qf_client'=> true,
'qf_rules' => array(
'required' => 'Date is required.',
),
),

It didn’t worked and also gave the javascript error as calendar.Setup – no such method found….
Now I started working on how to fix this problem. I started checking the all the codes thoroughly and found that using QuickForm from DB_Table setting all these options can’t be done. After spending some upon those codes I rewrite the column definition like this


'datefield1' => array(
'type' => 'varchar',
'size' => 20,
'qf_type' => 'jscalendar',
'qf_label'=> '<span class="caption">Date:</span>',
'require' => false,
'qf_attrs' => array('class'=> 'formfield','id' => 'datefield1'),
'qf_opts' => array(
'ifFormat' => '%d.%m.%Y',
'showsTime' => false,
'time24' => false,
'weekNumbers' => false,
'showOthers' => false,
'button' => '',
),
'qf_client'=> true,
'qf_rules' => array(
'required' => 'Date is required.',
),
),

Also I declared the global path defining variable in the page where I was generating the form. I defined


$GLOBALS['_HTML_QUICKFORM_JSCALENDAR_BASEPATH'] = "/js/jscalendar/";

Oh that time it worked. It showed the small calendar while the clicking the small button beside the text field for data. But I wasn’t still happy with it. What I found that the calendar was coming but it wasn’t using any style and dates are raveling upon a transparent layer, making it too ugly. I tried to define the style using style class/ stylesheet file name in different places as different parameter. But nothing worked. Now I had two options then

Define the stylesheet for the calendar within the head tags of the page containing the form, means hardcode the name of the stylesheet.
Change the coding to accommodate to options for setting the style class for the calendar.

Selecting the 1st option means loosing some dynamicity and selecting the 2nd option means I need to change or modify certain code in pear class package files. So it was difficult to select any option. I was investigating the benefits and the hitches which can come out as a result of using any one of those options. Also side by side I was looking for third other option which can be better then these two. I spent almost two days and came up with a decision of selecting the second option. I decided to add two lines of code in the QuicfForm.php file in the DB package as


if(isset($col['qf_theme'])) {
$element->theme = $col['qf_theme'];
}

Also I have added one more element in column definitions for the date field as


'datefield1' => array(
…… …….
…… …….
'qf_theme' => 'calendar-win2k-2',
),

Now my problem is solved and the jscalendar is working seamlessly with the QuickForm from the DB_Table package too.

My opinion is if you like to add the two lines of code in QuickForm.php file you can add it but you need to remember it at the time when you upgrade the pear package. Also you need to check if it works properly or not. The other way is to hardcode the stylesheet file within the head tag part of the page where you will go to generate the form. In this case you will surely loose some dynamicity but this is easier to work with. Choice is yours.

Currently I am working upon another important issue in php. I need some time to accomplish this job. I will discuss this issue too cause I find it very interesting. However if you find this above discussion useful then I might expect your comment here. Suggestion and queries are also welcome.