Rayhan’s blog (raynux.com)

Rayhan’s Personal Web Blog Site

Entries Comments


Send Mail From Unix/Linux Bash Shell Script

11 April, 2011 (12:30) | Linux, Reference | 1 comment

Tags: , , , , , , , ,


Bash shell script is very popular and widely used in Unix world for command automation and task scheduling using cron. Sometime it is very important to know the status of these scripts to make sure that they are working exactly the way you want and if any script fails you can take prompt actions.

The mail command, available in most of the Unix, Linux and Macs, can be used to send the status message right from your bash script so that you always know about your script’s activity.

In this article I am going to share some simple but important tricks on sending mail form shell script. Proper use of these tricks will increase the accountability of your scripts and let you relax at your work.

Simple shell script to send one line status mail.

#!/bin/bash
echo "Message Body!" | /usr/bin/mail -s "Message Title" example@example.com

What if you want to send a multi-line message? you can wrap your lines in a shell function and use the following code.

#!/bin/bash
function mystatus {
    echo "Script started successfully"
    echo "Backup operation completed successfully"
    echo "File transferred successfully"
}
mystatus | /usr/bin/mail -s "Message Title" example@example.com

Alternatively you can store messages in a temporary file and load the message body from the file

#!/bin/bash

TMPFILE="/tmp/mailbody.txt"
echo "Script started successfully" > $TMPFILE
echo "Backup operation completed successfully" >> $TMPFILE
echo "File transferred successfully" >> $TMPFILE

/usr/bin/mail -s "Message Title" example@example.com < $TMPFILE

A real example: how you can get the status email whether your MySQL database is backed up properly or not.

#!/bin./bash
function mysqlbackup {
    echo "Script started successfully"
    if (mysqldump -uusername -ppassword database_name > data.sql); then
        echo "MySQL database backed up successfully"
    else
        echo "Error: Could not take database backup!"
    fi

}
mysqlbackup | /usr/bin/mail -s "Backup Status" example@example.com

For more details about bash scripting read this Advance Bash-Scripting Guide.

Hope this simple  script will be helpful for you. Please let us know your feedback.

Introducing BankInfoBD.com – First Banking Portal in Bangladesh

27 December, 2010 (17:20) | Bangladesh, web, Web Services | 1 comment

Tags: , , , , , , ,


It’s been 2 months, we have started BankInfoBD.com project. Our goal is simple, provide all sort of banking information form one place, so that people can get their necessary banking information easily without wasting time and can compare each other.

why do you need a service like bankinfobd.com? Currently, all banks operating in Bangladesh has their own website. Among them only few banks updates their website regularly, not all banks have all products or service information on their websites and some are really outdated.

Moreover, each bank website has different information structure and user interface to serve information. So, if you want to find a specific information, say Car Loan, you have to go to different banks website and browse one by one in different ways. This way you can hardly get 5 to 6 banks car loans information wasting a big amount of time.

We are making this process easier with our Car Loan section, where you can get all banks who have Car Loans and browse one by one easily, if you feel more information then you can always visit the banks website.

“Time is important”, For bankers and people related to banking sector, we are serving latest banking news & event information in our news section, so you can now get updated in few minutes.

We also have a career section where we are putting tips and articles for novice bankers and also for those who are planning for banking career. Hope, this is going to be a great knowledge center for banking in near future.

Our banking blog section is open for all. It will help us to know more about in and out of our banking sector. Whether you are a banker or student, if you have a great article on Banking or you want to share ur banking experience, which you feel helpful for other, please write or email us at info.[at].bankinfobd.com, we will publish with your name and reference.

Features of BankInfoBD.com

Its one month, BankInfoBD.com is live on the internet. From the very beginning, we are getting excellent response from all and now we are more encouraged to work hard on it. Soon, we will come up with more ideas and information in this portal.

Standard Coding, OOP Techniques and Code Reuse

7 November, 2010 (16:48) | Bangladesh, PHP, programming, web | 2 comments

Tags: , , , , , , , , , ,


Yesterday, I have spoke on phpXperts 2010 seminar on “Standard Coding, OOP Techniques and Code Reuse“. So far this is the largest tech seminar in Bangladesh where more than 350 programmers attended excluding the speakers and sponsors. The event has also being broadcasted live on the web. The audience enjoyed the event very much from first to last which made this event a huge success in its kind. I am really glad to be part of such a great event. I would like to thank phpXperts & Hasin Hyder for such an opportunity. I have embedded my slides bellow.

If you find my presentation helpful for you, please rate my slides at SpeakerRate.com.

More about the seminar:

RayCrypt – PHP Class for Quick Two Way Encryption and Decryption

6 November, 2010 (19:26) | PHP, PHP Classes, programming, Reference, web security | 5 comments

Tags: , , , , , , , , ,


RayCrypt, A simple and easy PHP class for two way encryption and decryption with multiple configurations and plug and play features.

Sometimes two way encryption is very much important when it comes in storing credential information. Credit Card, Bank account information, digital signature etc are very important information of user and strongly discouraged to store in plain text. These data should always be stored in encrypted format. PCI has a very strict guideline and policy for storing Credit Card Information in database or file.

This class is very handy to solve this type of situation.

Features:

- Simple & Easy to use from anywhere in your application with a single line of code.
- Easily configurable & can work without any configuration.
- Support multiple salt configurations
- Requires PHP Mcrypt library installed
- Static method for encryption and decryption
- Light Weight

Method:

- RayCrypt::encrypt();
- RayCrypt::decrypt();
- RayCrypt::config();
- RayCrypt::padString();

Class:

File: raycrypt.php

<?php
/**
 * Two way Encryption and Decryption Class.
 *
 * Suitable for storing credential information like credit card, bank account information into the database
 *
 * PHP version 5+
 * - require Mcrypt library installed
 *
 * @package     raynux
 * @subpackage  raynux.labs.crypt
 * @version     1.0
 * @author	Md. Rayhan Chowdhury
 * @license     MIT License http://www.opensource.org/licenses/mit-license.php
 */

/**
 * Encrypt & Decrypt Using PHP MCrypt Library
 *
 * @package     raynux
 * @subpackage  raynux.labs.crypt
 * @author      Md. Rayhan Chowdhury
 */
class RayCrypt{

    /**
     * RayCrypt Instances
     *
     * @var RayCrypt
     */
    protected static $_instances = array();

    /**
     * Secret Salt generated from the key
     *
     * @var string
     */
    protected $_secretKey;

    /**
     * Default Configuration Array
     *
     * @var array
     */
    protected $_defaults = array(
                                    'returnPlainText' => true,
                                    'salt' => '7$e4!158f6$%#be533.!@a066!#35428^#%&$*&faa91:!982*#!e07'
                                );

    /**
     * Hold Run-time configuration
     *
     * @var array
     */
    protected $_configs = array();

    /**
     * Class Constructor
     *
     * @param array $options
     */
    private function __construct($options = null) {
        $this->_setConfig($options);
    }

    /**
     * Get Instance of RayCrypt
     *
     * @param string $configName
     * @param array $options
     * @return RayCrypt
     */
    private static function &_getInstance($configName = null, $options = null) {

        if (empty($configName)) {
            $configName = 'default';
        }

        if (empty(self::$_instances[$configName])) {
            self::$_instances[$configName] = new self($options);
        }

        return self::$_instances[$configName];
    }

    /**
     * Configure the class instance
     *
     * @param array $options  array('salt' => '', 'returnPlainText' => true)
     * @return RayCrypt
     */
    protected function &_setConfig($options = null) {

        if (empty($options) || !is_array($options)) {
            $options = array();
        }

        $this->_configs = array_merge($this->_defaults, $options);

        if (!empty($this->_configs['salt'])) {
            $this->_setSecretKey($this->_configs['salt']);
        }

        return $this;
    }

    /**
     * Set secret salt for encryption algorithm
     * @param string $key
     * @return RayCrypt
     * @access protected
     */
    protected function &_setSecretKey($key) {
        $this->_secretKey = md5(substr(sha1($key), 0, 32));
        return $this;
    }

    /**
     *
     * @param  $configName
     * @param  $options
     */
    public static function config($configName, $options = null) {
        $_this = self::_getInstance($configName, $options);
    }

    /**
     * Encrypt using Mcrypt PHP Library
     *
     * @param string $value
     * @param string $configName
     * @return string
     * @access public
     * @static
     */
    public static function encrypt($value, $configName = null) {

        $_this = self::_getInstance($configName);
        $key = $_this->_secretKey;

        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        $encryped = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $value, MCRYPT_MODE_ECB, $iv);
        if (!empty($_this->_configs['returnPlainText'])) {
            $encryped = base64_encode($encryped);
        }

        return $encryped;
    }

    /**
     * Decrypt Using Mcrypt
     *
     * @param string $value
     * @param string $configName
     * @return string
     * @access public
     * @static
     */
    public static function decrypt($value, $configName = null) {
        $_this = self::_getInstance($configName);
        $key = $_this->_secretKey;

        if (!empty($_this->_configs['returnPlainText'])) {
            $value = base64_decode($value);
        }

        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
        return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $value, MCRYPT_MODE_ECB, $iv), "\0\4");
    }

    /**
     * Masks Important Information Padding String
     *
     * helpful in displaying a part of credit card information like
     * 01234567890 will result xxxxxxx7890
     *
     * @param string $string
     * @param integer $length specify negative length to mask from backward
     * @param mask character $maskCharacter
     * @return string
     * @access public
     * @static
     */
    public static function padString($string, $length, $maskCharacter = 'X') {
        $maskString = substr($string, 0, $length);
        $maskString = preg_replace('(.)', $maskCharacter, $maskString);
        $string = $maskString . substr($string, $length);
        return $string;
    }

}

?>

Usage Example: some quick examples are given below to introduce you with the class and it’s methods.

<?php
/**
 * RayCrypt Example File
 */

/**
 * Load RayCrypt Library
 */
include_once 'raycrypt.php';

/**
 * Basic debug function
 *
 * @param mixed $value
 */
function dump ($value) {
    printf('<pre>%s</pre>', var_export($value, true));
};

/**
 * Use RayCrypt without any configuration, it uses default configuration
 */
$data = 'My important data';
$encrypted = RayCrypt::encrypt($data);
$decrypted = RayCrypt::decrypt($encrypted);
dump(array('data' => $data, 'encrypted' => $encrypted, 'decrypted' => $decrypted));

/**
 * Output
 array (
  'data' => 'My important data',
  'encrypted' => 'JBtn3msE0QIAei/v9oHP5nW2xasbdSeVhAb4nPXqiUA=',
  'decrypted' => 'My important data',
)
 */

/**
 * Use RayCrypt with a separate configuration salt for creditCard information
 */
RayCrypt::config('creditCard', array('salt' => 'jdfjsddfsdf!$#fjsdkjfsdfi7*@(@sdhf'));
$data = '01234567890';
$encrypted = RayCrypt::encrypt($data, 'creditCard');
$decrypted = RayCrypt::decrypt($encrypted, 'creditCard');
dump(array('data' => $data, 'encrypted' => $encrypted, 'decrypted' => $decrypted));

/**
 * Output
array (
  'data' => '01234567890',
  'encrypted' => 'E9FO62vScqmObOlIXso70Hx8JpEqzVOiac8yuk3/4yM=',
  'decrypted' => '01234567890',
)
 */

/**
 * Use RayCrypt with a another configuration for bank information
 */
RayCrypt::config('bank', array('salt' => 'Nothing wrong'));
$data = '884585847';
$encrypted = RayCrypt::encrypt($data, 'bank');
$decrypted = RayCrypt::decrypt($encrypted, 'bank');
dump(array('data' => $data, 'encrypted' => $encrypted, 'decrypted' => $decrypted));

/**
 * Output
array (
  'data' => '884585847',
  'encrypted' => 'BnDAjNJq/ZrwEKT9yLVFEVZO0b4/uu2AWRGVhX3mVRw=',
  'decrypted' => '884585847',
)
 */

dump(RayCrypt::padString('0123456789', -4)); // output 'XXXXXX6789'

?>

Please let me know if you find this class helpful for you..

RayCache – An Easy, Multiple Configurable PHP Caching Class

8 August, 2010 (03:11) | class, PHP, programming, Reference | 4 comments

Tags: , , , ,


RayCache, A Simple and Easy PHP Caching Class with multiple configurations and plug and play features.

Ever needed a quick caching class for your PHP application? This is another caching class for PHP which is able to solve your quick caching needs. Now a days all major frameworks comes with a standard caching library. But, in some cases you may need only a caching class. It is also helpful when you are not using framework or if you don’t like the cache class provided by the framework. In my case, I am using CodeIgniter for last few months and I am not happy with the caching solution provided by CodeIgniter.

Since, I am a CakePHP lover, I have looked at CakePHP cache library and tried to make something similar. So, you may find similarity with CakePHP.

Features:

- Simple & Easy to use from anywhere in your application with a single line of code.
- Easily configurable & can work without any configuration.
- Support multiple cache configurations
- Support static method for caching
- Support file caching engine for now, other caching engines can be added to the class
- Support singleton pattern
- Light Weight

Class:

File: raycache.php

<?php 
/*	SVN FILE: $Id: raycache.php 85 2008-05-13 07:36:10Z rayhan $	 */
/**	Cache Object Class.
*
*	Caching classes for easy and plug and play installation.
* 
*	PHP version 5+
*	
*	
*	@copyright		Copyright 2006-2010, Md. Rayhan Chowdhury
*	@package		raynux
*	@subpackage		raynux.labs.cache
*	@version		$Revision: 85 $
* 	@modifiedby		$LastChangedBy: rayhan $
*	@lastModified           $Date: 2008-05-13 13:36:10 +0600 (Tue, 13 May 2008) $
*	@author			$Author: rayhan $
*	@website		www.raynux.com
*       @license                MIT License http://www.opensource.org/licenses/mit-license.php
*/


/**
 * Cache Engine Interface
 * 
 */
Interface RayCacheEngineInterface{
    function write($key, $data, $options = array());
    function read($key, $options = array());
    function delete($key, $options = array());
    function clear($expired = true);
    function gc();
    public static function &getInstance($configs = array());
}

/**
 * Cache Class
 *
 * Provide cache functionality for multiple configuration and engine.
 * Static read-write method are helpful to call from anywhere of the script.
 *
 * @package raynux
 * @subpackage raynux.labs.cache
 */
class RayCache{
    /**
     * Class Instances
     *
     * @var array
     */
    private static $__instances = array();

    /**
     * Get Instance of a cache engine
     *
     * Factory Interface for Cache Engine.
     *
     * @param config $configName
     * @param string $engine default file
     * @param array $configs
     * @return object
     */
    public static function &getInstance($configName = null, $engine = null, $configs = array()){
        if (empty($configName)) {
            $configName = 'default';
        }

        if (empty($engine)) {
            $engine = 'file';
        }

        if (isset(self::$__instances[$configName])) {
            return self::$__instances[$configName];
        }

        if (empty(self::$__instances)) {
            $default = true;
        }

        $engine = strtolower($engine);

        switch ($engine){
            case 'file':
            default:
                self::$__instances[$configName] = new RayFileCache($configs);
                break;
        }

        return self::$__instances[$configName];
    }

    /**
     * Static wrapper to cache write method
     *
     * @param string $key
     * @param mixed $data
     * @param array $options, array('expire' => 10), expire in seconds
     * @param string $configName 
     * @return boolean
     */
    public static function write($key, $data, $options = array(), $configName = 'default') {
        $_this = self::getInstance($configName);
        return $_this->write($key, $data, $options);
    }

    /**
     * Static Wrapper to cache read method
     *
     * @param string $key
     * @param array $options
     * @param string $configName 
     * @return mixed
     */
    public static function read($key, $options = array(), $configName = 'default') {
        $_this = self::getInstance($configName);
        return $_this->read($key, $options);
    }

    /**
     * Static wrapper to cache delete mathod
     *
     * @param string $key
     * @param array $options
     * @param string $configName
     * @return boolean
     */
    public static function delete($key, $options = array(), $configName = 'default') {
        $_this = self::getInstance($configName);
        return $_this->delete($key, $options);
    }
}


/**
 * File Cache Engine
 *
 * @package raynux
 * @subpackage raynux.labs.cache
 */
class RayFileCache implements RayCacheEngineInterface{
    /**
     * Class Instances
     * 
     * @var array
     */
    private static $__instance;

    /**
     * Runtime Configuration Data
     * 
     * @var array
     */
    protected $_configs = array();

    /**
     * Class Constructor
     * 
     * @param array $configs
     */
    function  __construct($configs = array()) {
        $this->config($configs);

        // run garbage collection
        if (rand(1, $this->_configs['gc']) === 1) {
            $this->gc();
        }
    }

    /**
     * Get Instance of Class
     *
     * @param string $name
     * @param array $configs
     * @return object
     * @static
     */
    public static function &getInstance($configs = array()){
        if (is_null(self::$__instance)) {
            self::$__instance = new self($configs);
        }
        return self::$__instance;
    }

    /**
     * Set Configuration
     *
     * default: array('path' => './cache/', 'prefix' => 'raycache_', 'expire' => 10, 'gc' => 100)
     *
     * @param array $configs
     * @return object self instance
     */
    function &config($configs = array()) {
    	// default path modified to work with ci cache
        $default = array('path' => './cache/', 'prefix' => 'raycache_', 'expire' => 10, 'gc' => 100);
        $this->_configs = array_merge($default, $configs);
        return $this;
    }

    /**
     * Write data to cache
     *
     * @param string $key
     * @param mixed $data
     * @param array $options
     * @return boolean
     */
    public function write($key, $data, $options = array()){
        // check is writable
        if (!is_writable($this->_configs['path'])) {
            echo $this->_configs['path'];
            return false;
        }

        // Prepare data for writing
        if (!empty($options['expire'])) {
            $expire = $options['expire'];
        } else {
            $expire = $this->_configs['expire'];
        }

        if (is_string($expire)) {
            $expire = strtotime($expire);
        } else {
            $expire = time() + $expire;
        }
        
        $data = serialize(array('expire' => $expire, 'data' => $data));

        $fileName = $this->_configs['path'] . $this->_configs['prefix'] . $key;
        
        // Write data to files
        if (file_put_contents($fileName, $data, LOCK_EX)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Read Data from cache 
     * 
     * @param string $key
     * @param array $options
     * @return mixed
     */
    public function read($key, $options = array()) {
        $fileName = $this->_configs['path'] . $this->_configs['prefix'] . $key;

        if (!file_exists($fileName)) {
            return false;
        }

        if (!is_readable($fileName)) {
            return false;
        }

        $data = file_get_contents($fileName);
        if ($data === false) {
            return false;
        }
        
        $data = unserialize($data);
        
        if ($data['expire'] < time()) {
            $this->delete($key);
            return false;
        }

        return $data['data'];
    }

    /**
     * Delete a cache data
     * 
     * @param string $key
     * @param arrayt $options
     * @return boolean
     */
    function delete($key, $options = array()) {
        $fileName = $this->_configs['path'] . $this->_configs['prefix'] . $key;
        if (!file_exists($fileName) || !is_writable($fileName)) {
            return false;
        }
        return unlink($fileName);
    }

    /**
     * Clear cache data
     *
     * @param boolean $expired if true then only delete expired cache
     * @return booelan
     */
    public function clear($expired = true) {
        $entries = glob($this->_configs['path'] . $this->_configs['prefix'] . "*");

        if (!is_array($entries)) {
            return false;
        }

        foreach ($entries as $item) {
            if (!is_file($item) || !is_writable($item)) {
                continue;
            }

            if ($expired) {
                $expire = file_get_contents($item, null, null, 20, 11);

                $strpos = strpos($expire, ';');
                if ($strpos !== false) {
                    $expire = substr($expire, 0, $strpos);
                }

                if ($expire > time()) {
                    continue;
                }
            }
            
            if (!unlink($item)) {
                return false;
            }
        }
        
        return true;
    }

    /**
     * Garbage collection
     * 
     * @return boolean
     */
    public function gc() {
        return $this->clear(true);
    }
}

?>

Usage Example: some quick examples are given below to introduce you with the class and it’s methods.

<?php
    /**
     * Load the cache library
     * 
     */
    include_once('raycache.php');

    /**
     * Class Example
     * 
     * Once loaded you can use this class in two ways:
     * - Using Static Methods (My Favorite)
     * - Using Class Instance
     * 
     * or, even you can mix them both
     * In both ways it support multiple configuration and uses
     */

    /**
     * Static Method
     */

    //Get default CacheInstance with one of the following methods
    RayCache::getInstance();

    // OR
    RayCache::getInstance(null, null, array('path' => 'my_cache_path/', 'prefix' => 'my_cache_', 'expire' => '+10 seconds'));

    // You can configure or reconfigure your instance anytime you like.
    RayCache::getInstance()->config(array('path' => 'my_cache_path/', 'prefix' => 'my_cache_', 'expire' => '+10 seconds'));

    // store data
    RayCache::write('test_key', 'This data will expire in 10 seconds
'); RayCache::write('test_key2', 'This data will expire in 10 seconds
', array('expire' => '+10 seconds')); // expre value can be integer in seconds or time string supported by php strtotime method RayCache::write('test_key3', 'This data will expire in 20 seconds
', array('expire' => '+20 seconds')); // read data echo RayCache::read('test_key'); echo RayCache::read('test_key2'); echo RayCache::read('test_key3'); /** * Class Instance Method */ // get calss class instance $cache = RayCache::getInstance(); // default configure $cache2 = RayCache::getInstance('short', null, array('prefix' => 'short_', 'path' => 'my_cache_path/', 'expire' => '+20 seconds')); $cache3 = RayCache::getInstance('long', null, array('prefix' => 'long_', 'path' => 'my_cache_path/', 'expire' => '+1 hour')); // store data $cache->write('test_key', 'This data will expire in 10 seconds
'); $cache2->write('test_key2', 'This data will expire in 20 seconds
'); $cache3->write('test_key3', 'This data will expire in 1 hour
'); // read data echo $cache->read('test_key'); echo $cache2->read('test_key2'); echo $cache3->read('test_key3'); ?>

Please let me know if you find this class helpful for you..

Microsoft’s Initiatives for PHP Developers

16 October, 2009 (12:07) | Developer, Interoperability, Microsoft, PHP, PHP Classes, WebsiteSpark, Windows Azure | 1 comment

Tags: , , , , , ,


For years Software Engineers have been trying to get the best out of Opensource, PHP and Microsoft Products. Because of Microsoft business policy they were not successful enough. Finally, Microsoft understood the reality and started to bend towards PHP. Now they wants to make their Platform more compatible to work with PHP. Microsoft has taken several initiatives to open their door for PHP Developers. Some of them are explained bellow:

WebsiteSpark:

It aims to promote the careers of PHP and other Web professionals in general that are interested in specializing in the Microsoft technologies. Under this project they will provide software, support and visibility to the Web Professionals. It’s a three years long program and you will have to pay a one time program fee of  $100 which is due upon exit or at the end of three years term.

Once enrolled, they are giving away following software products:

- Visual Studio 2008 Professional Edition – 3 licences
- Expression Studio 3 – 1 licence
- Expression Web 3 – 2 licences
- Windows Web Server 2008 R2 – licences for 4 processors (production and development)
- SQL Server 2008 Web Edition – licences for 4 processors (production and development)
- DotNetPanel Control Panel

These offer is for small company having employees 10 or less than 10.

You can find more details on project website: http://www.microsoft.com/web/websitespark/

A Microsoft Manager (Galileu Vieira) explained the offer in details in an interview with PHPClasses.org here: http://www.phpclasses.org/blog/post/102-Microsoft-promotes-the-careers-of-PHP-professionals.html
. And if you read this blog post then I suggest to read the following comment tread also. http://www.phpclasses.org/discuss/blog/PHP-Classes-blog/post/102/thread/12/

Here is another post on Microsoft and PHP at PHPClasses.org: http://www.phpclasses.org/blog/post/85-What-is-Microsoft-up-to-with-PHP.html

Interoperability:

A Center run by Microsoft Interoperability Strategy Group, which is dedicated to technical collaborative work to improve interoperability between Microsoft and non-Microsoft technologies. In this site, you will find a live directory of freely downloadable technical interoperability Bridges & Labs and related content such as demos, technical guidance and articles. The vast majority of the projects are Open Source. Here you will meet with PHP Interoperability projects and technologies.

Mode details at Centers website: http://www.interoperabilitybridges.com/Default.aspx

Windows Azure:

What is Windows Azure? In their words, it is Microsoft’s Platform to run interoperable application and services. Windows Azure is a runtime environment in the cloud that delivers on-demand compute, storage, and automated systems management. Windows Azure provides developers with the ability to host, scale, and manage Web applications on the Internet through Microsoft data centers.

More details at Windows Azure website: http://www.azure.com/

RayFeedReader – PHP class for parsing RSS and Atom Feed

2 September, 2009 (00:35) | class, FEED, PHP, programming, Reference | 3 comments

Tags: , , , , , ,


RayFeedReader, A Simple and Easy SimpleXML based feed reader class using PHP.

First of all it’s another reinvention of wheel. This class is designed to provide quick access to any XML based RSS feed and it’s content. Usages are very simple and require only one line of code. Html rendering functionality is provided through separate pluggable widget rendering class which can be extended easily. SimpleXML is used by default to load and fetch feed url but can be used CURL using rayHttp class. All or any CURL options can be set for HTTP request. It can auto detect feed type and supports RSS 0.92, RSS 2.0 and Atom feeds.

Features:

- Read feeds content into an array
- Supports for RSS 0.92, RSS 2.0 and Atom feed
- Detect feed type automatically, also can be set manually.
- Support pluggable html widget rendering class
- Can render html widget through optional RayFeedWidget class or your own extended class.
- Easily configurable & can work without any configuration.
- Simple & Easy to use from anywhere in your application with a single line of code.
- Support Singleton pattern
- By default SimpleXML is used as http client,
- Support Custom CURL request, may be used to extends functionality through rayHttp class.
- Light Weight

Methods Available (This class provides):
- parse()
- getData()
- widget()

Class:

File: rayfeedreader.php

<?php

    /**
     * RayFeedReader
     *
     * SimpleXML based feed reader class. A very specific feed reader designed
     * to working with no or little configurations.
     *
     * - This class can read an rss feed into array from a given url.
     * - Also can render html widget with plugable RayFeedWidget Class.
     * 
     * Supports following feed types:
     *  - RSS 0.92
     *  - RSS 2.0
     *  - Atom
     *
     * Configuration Options
     *  - array
     *      - url: (string)
     *          - feed url
     *
     *      - httpClient: (string)
     *          - default SimpleXML
     *          - value rayHttp or SimpleXML
     *
     *      - type: ([optional] string
     *          - auto detect
     *          - value rss or rss2 or atom
     *
     *      - widget: ([optional] string)
     *          - feed widget class name for rendering html
     * 
     *      - rayHttp: (array)
     *          - only if httpClient is set to rayHttp
     *          - rayHttp Options if you want to modify rayHttml CURL options
     *          - generally not required.
     *
     *
     * 
     *
     * @version 1.0
     * @author Md. Rayhan Chowdhury
     * @package rayFeedReader
     * @license GPL
     */
    Class RayFeedReader{

        /**
         * Self Instance for Singleton Pattern
         *
         * @var object
         * @access protected
         */
        static private  $__instance;

        /**
         * Instance of Parser Class.
         *
         * @var object Parser Class
         * @access protected
         */
        Protected       $_Parser;

        /**
         * Feed Url
         *
         * @var string feed url
         * @access protected
         */
        protected       $_url;

        /**
         * Runtime Options for reader
         *
         * @var array
         * @access protected
         */
        protected       $_options = array('rayHttp' => array());

        /**
         * Type of feed to be parsed.
         *
         * @var string
         * @access protected
         */
        protected       $_type = "rss";

        /**
         * HttpClient to be used for loading feed content.
         *
         *  - default SimpleXML
         *
         * @var string 'SimpleXML' or 'rayHttp'
         * @access protected
         */
        protected       $_httpClient = "SimpleXML";
        
        /**
         * Widget Class Name
         *
         * @var string
         * @access protected
         */
        protected       $_widget;

        /**
         * Parsed result data
         * 
         * @var array
         * @access protected
         */
        protected       $_content;

        /**
         * Class construct
         *
         * @param array $options
         */
        function __construct($options = array()) {
            $this->setOptions($options);
        }

        /**
         * Get Instance of the class.
         *
         * @param array $options
         * @return object self instance.
         * @access public
         * @static
         */
        static function &getInstance($options = array()) {
            if (is_null(self::$__instance)) {
                self::$__instance = new self($options);
            }
            return self::$__instance;
        }

        /**
         * Set Options for the class
         * 
         * 
         * @param array $options
         * @return object self instance
         * @access public
         */
        function &setOptions($options) {
            if (!empty($options['url'])) {
                $this->_url = $options['url'];
            }

            if (!empty($options['type'])) {
                $this->_type = $options['type'];
            }

            if (!empty($options['httpClient'])) {
                $this->_httpClient = $options['httpClient'];
            }

            if (!empty($options['widget'])) {
                $this->_widget = $options['widget'];
            }

            $this->_options = array_merge($this->_options, $options);

            return $this;
        }

        /**
         * Parse feed contents into an array and return self object
         * 
         * @return object self instance
         * @access public
         */
        function &parse() {
            /**
             * Get/load content
             */
             switch ($this->_httpClient) {
                 case 'SimpleXML':
                     $content = new SimpleXMLElement($this->_url, LIBXML_NOCDATA, true);
                     break;

                 case 'rayHttp':
                     
                     $content = RayHttp::getInstance()->setOptions($this->_options['rayHttp'])->get($this->_url);
                     
                     if (!empty($content)) {
                        $content = new SimpleXMLElement($content, LIBXML_NOCDATA);
                     }
                     break;
             }

             if (empty($content)) {
                 trigger_error("XML format is invalid or broken.", E_USER_ERROR);
             }

            /**
             * Detect Feed Type
             */

             if (empty($this->_type)) {
                    
                    switch ($content->getName()) {
                        case 'rss':
                            foreach ($content->attributes() as $attribute) {
                                if ($attribute->getName() == 'version') {
                                    if ('2.0' == $attribute) {
                                        self::setOptions(array('type' => 'rss2'));
                                    } elseif (in_array($attribute, array('0.92', '0.91'))) {
                                        self::setOptions(array('type' => 'rss'));
                                    }
                                }
                            }
                            break;

                        case 'feed':                            
                            self::setOptions(array('type' => 'atom'));
                            
                            break;
                    }
                 
             }
             
             if (!in_array($this->_type, array('rss', 'rss2', 'atom'))) {

                  trigger_error("Feed type is either invalid or not supported.", E_USER_ERROR);
                  
                  return false;
             }


            /**
             * Parse Feed Content
             */
            switch ($this->_type) {
                case 'rss':
                    $content = $this->parseRss($content);
                    break;

                case 'rss2':
                    $content = $this->parseRss2($content);
                    break;

                case 'atom':
                    $content = $this->parseAtom($content);
                    break;
            }

             if (empty($content)) {                 
                 trigger_error("No content is found.", E_USER_ERROR);
             }

             $this->_content = $content;
             
             return $this;

        }

        /**
         * Get Array of Parsed XML feed data.
         *
         * @return array parsed feed content.
         * @access public
         */
        function getData() {
            return $this->_content;
        }

        /**
         * Return html widget based rendered by widget class
         *
         *
         * @param array $options for html widget class
         * @return string html widget
         * @access public
         */
        function widget($options = array('widget' => 'brief')) {
            if (!empty($this->_widget) && !empty($this->_content)) {
                $Widget = new $this->_widget;
                
                return $Widget->widget($this->_content, $options);
                
             } else {
                 return false;
             }
        }
        
        /**
         * Parse feed xml into an array.
         *
         * @param object $feedXml SimpleXMLElementObject
         * @return array feed content
         * @access public
         */
        function parseRss($feedXml) {
            $data = array();

            $data['title'] = $feedXml->channel->title . '';
            $data['link'] = $feedXml->channel->link . '';
            $data['description'] = $feedXml->channel->description . '';
            $data['parser'] = __CLASS__;
            $data['type'] = 'rss';

            foreach ($feedXml->channel->item as $item) {
                $data['items'][] = array(
                                        'title' =>  $item->title . '',
                                        'link' =>   $item->link . '',
                                        'description' => $item->description . '',
                                    );
            }
            
            return $data;
        }

        
        /**
         * Parse feed xml into an array.
         *
         * @param object $feedXml SimpleXMLElementObject
         * @return array feed content
         * @access public
         */
        function parseRss2($feedXml) {
            $data = array();

            $data['title'] = $feedXml->channel->title . '';
            $data['link'] = $feedXml->channel->link . '';
            $data['description'] = $feedXml->channel->description . '';
            $data['parser'] = __CLASS__;
            $data['type'] = 'rss2';

            $namespaces = $feedXml->getNamespaces(true);
            foreach ($namespaces as $namespace => $namespaceValue) {
                $feedXml->registerXPathNamespace($namespace, $namespaceValue);
            }

            foreach ($feedXml->channel->item as $item) {
                $categories = array();
                foreach ($item->children() as $child) {
                    if ($child->getName() == 'category') {
                        $categories[] = (string) $child;
                    } 
                }

                $author = null;
                if (!empty($namespaces['dc']) && $creator = $item->xpath('dc:creator')) {
                    $author = (string) $creator[0];
                }

                $content = null;
                if (!empty($namespaces['encoded']) && $encoded = $item->xpath('content:encoded')) {
                    $content = (string) $encoded[0];
                }

                $data['items'][] = array(
                                        'title' =>  $item->title . '',
                                        'link' =>   $item->link . '',
                                        'date' =>   date('Y-m-d h:i:s A', strtotime($item->pubDate . '')),
                                        'description' => $item->description . '',
                                        'categories' => $categories,
                                        'author' => array( 'name' => $author),
                                        'content' => $content,
                                        
                                    );
                
            }

            return $data;
        }

        /**
         * Parse feed xml into an array.
         *
         * @param object $feedXml SimpleXMLElementObject
         * @return array feed content
         * @access public
         */
        function parseAtom($feedXml) {
            $data = array();

            $data['title'] = $feedXml->title . '';
            foreach ($feedXml->link as $link) {
                    $data['link'] = $link['href'] . '';
                break;
            }

            $data['description'] = $feedXml->subtitle . '';
            $data['parser'] = __CLASS__;
            $data['type'] = 'atom';

            foreach ($feedXml->entry as $item) {
                foreach ($item->link as $link) {
                    $itemLink = $link['href'] . '';
                    break;
                }

                $categories = array();
                foreach ($item->category as $category) {
                    $categories[] = $category['term'] . '';
                }

                $data['items'][] = array(
                                        'title' =>  $item->title . '',
                                        'link' =>   $itemLink . '',
                                        'date' =>   date('Y-m-d h:i:s A', strtotime($item->published . '')),
                                        'description' => $item->summary . '',
                                        'content' => $item->content . '',
                                        'categories' => $categories,
                                        'author' => array('name' => $item->author->name . '', 'url' => $item->author->uri . ''),
                                        'extra' => array('contentType' => $item->content['type'] . '', 'descriptionType' => $item->summary['type'] . '')
                                    );
            }

            return $data;
        }

    }
?>

External feed widget class to get rendered html widget.

File: rayfeedwidget.php

<?php

    /**
     * Feed Widget Interface
     *
     * @version 1.0
     * @author Md. Rayhan Chowdhury
     * @package rayFeedReader
     * @license GPL
     */
    interface RayFeedWidget_Interface{
        /**
         * Public widget method
         *
         * @param <type> $data
         * @param  $options
         * @return string html
         */
        public function widget($data, $options = array());
    }

    /**
     * Widget Plugin Class for RayFeedReader
     *
     * Render html widget for feed reader based on options
     *
     * config options
     *  - array
     *      - widget:
     *          - optional string
     *          - value 'brief' or 'compact' or 'detail'
     *      - showTitle
     *          - boolean
     *          - whether add blog title or not.
     *
     * @version 1.0
     * @author Md. Rayhan Chowdhury
     * @package rayFeedReader
     * @license GPL
     */
    class RayFeedWidget implements RayFeedWidget_Interface{

        /**
         * HTML widget structure
         *
         * @var array
         * @access public
         */
        public $html = array('brief' => "<div class=\"feed-item feed-brief\">\n
                                            <div class=\"feed-item-title\">\n
                                                <h3><a href='%s'>%s</a></h3>\n
                                                <div class='feed-item-date'>%s</div>\n
                                            </div>\n
                                            <div class=\"feed-item-description\">%s</div>\n
                                        </div>",
            
                                'compact' => "<div class=\"feed-item feed-compact\">\n
                                    <div class=\"feed-item-title\">\n
                                        <h3><a href='%s'>%s</a></h3>\n
                                        <div class='feed-item-date'>%s</div>\n
                                    </div>\n
                                </div>",

                                'detail' => "<div class=\"feed-item feed-detail\">\n
                                    <div class=\"feed-item-title\">\n
                                        <h3><a href='%s'>%s</a></h3>\n
                                        <div class='feed-item-date'>%s</div>\n
                                    </div>\n
                                    <div class=\"feed-item-content\">%s</div>\n
                                </div>",
                            );
        
        /**
         * Return html widget based rendered by widget class
         *
         * @param  $data
         * @param  $options
         * @return 
         */
        function widget($data, $options = array('widget' => 'brief')) {
            switch ($options['widget']) {

                case 'compact':
                    return $this->widgetCompact($data, $options);
                    break;

                case 'detail':
                    return $this->widgetDetail($data, $options);
                    break;
                
                case 'brief':
                default:
                    return $this->widgetBrief($data, $options);
                    break;
            }
        }

        /**
         * Render feed widget with title and date only
         *
         * @param  $data
         * @param  $options
         * @return  
         */
        function widgetCompact($data, $options = array()) {
            if (empty($data['items'])) {
              return false;
            }

            $out = array();
            foreach ($data['items'] as $item) {
                if (empty($item['date'])) {
                    $item['date'] = '';
                }
                $out[] = sprintf($this->html['compact'], $item['link'], $item['title'], $item['date']);

            }

            $title = '';
            if (empty($options['showtitle'])) {
                $title = sprintf("<div class='feed-title'><h2>%s</h2><hr>%s</div>\n", $data['title'], $data['description']);
            }

            $out = "<div class='feed-container'>\n"  . $title . join(" \n", $out) . "</div>";

            return $out;
        }

        /**
         * Render feed widget with title, date & description
         *
         * @param  $data
         * @param  $options
         * @return  
         */
        function widgetBrief($data, $options = array()) {
            if (empty($data['items'])) {
              return false;
            }

            $out = array();

            foreach ($data['items'] as $item) {
                if (empty($item['date'])) {
                    $item['date'] = '';
                }

                if (empty($item['description'])) {
                        $item['description'] = $item['content'];
                }
                
                $out[] = sprintf($this->html['brief'], $item['link'], $item['title'], $item['date'], $item['description']);

            }
            
            $title = '';
            if (empty($options['showtitle'])) {
                $title = sprintf("<div class='feed-title'><h2>%s</h2><hr>%s</div>\n", $data['title'], $data['description']);
            }

            $out = "<div class='feed-container'>\n"  . $title . join(" \n", $out) . "</div>";
            

            return $out;
        }

        /**
         * Render blog widget with title, date & content
         *
         * @param  $data
         * @param  $options
         * @return  
         */
        function widgetDetail($data, $options = array()) {
            if (empty($data['items'])) {
              return false;
            }

            $out = array();
            foreach ($data['items'] as $item) {
                if (empty($item['date'])) {
                    $item['date'] = '';
                }
                if (empty($item['content'])) {
                    $item['content'] = $item['description'];
                }
                $out[] = sprintf($this->html['detail'], $item['link'], $item['title'], $item['date'], $item['content']);

            }
            
            $title = '';
            if (empty($options['showtitle'])) {
                $title = sprintf("<div class='feed-title'><h2>%s</h2><hr>%s</div>\n", $data['title'], $data['description']);
            }

            $out = "<div class='feed-container'>\n"  . $title . join(" \n", $out) . "</div>";

            return $out;
        }
    }
?>

Usage Example: some quick examples are given below to introduce you with the class and it’s methods.

File: example.php

<?php
   
    /**
     * Example Usage or RayFeedReader
     */
   
    require_once('rayfeedreader.php');   
   
    /**
     * get Instance
     */
    $reader1 = RayFeedReader::getInstance();
    $reader2 = RayFeedReader::getInstance($options);
    $reader3 = new RayFeedReader();
    $reader4 = new RayFeedReader($options);

    /**
     * get data from a feed url
     */
    $options = array('url' => 'http://example.com/feed');

    $feedData = RayFeedReader::getInstance($options)->parse()->getData();

    // Or options can be set anytime using setOptions method.
    $feedData = RayFeedReader::getInstance()->setOptions($options)->parse()->getData();

    /**
     * Get html widget
     */

    $options = array(
                        'url' => 'http://example.com/feed',
                        'widget' => 'RayFeedWidget',
                    );
    
    /**
     * Load rayFeedWidget class file
     */
    require_once('rayfeedwidget.php');

    $html = RayFeedReader::getInstance()->setOptions($options)->parse()->widget();

    // OR with widget options.
    $widgetOptions = array('widget' => 'detail', 'showTitle' => true);
    
    $html = RayFeedReader::getInstance()->setOptions($options)->parse()->widget($widgetOptions);

    /**
     * Full options
     */
    $options = array(
                        'url' => 'http://example.com/feed',
                        'widget' => 'RayFeedWidget',
                        'httpClient' => 'rayHttp',
                        'type' => 'atom',
                    );

    /**
     * Load rayHttp class file.
     */
    require_once("rayhttp.php");    

    /**
     * Html widget with full options
     */
    $html = RayFeedReader::getInstance()->setOptions($options)->parse()->widget();

    /**
     * Get Feed Data with full options
     */
    $feedData = RayFeedReader::getInstance($options)->parse()->getData();
?>

Please let me know if you find this class helpful for you..

Class Update:

An updated version of this class and example script are posted at PHPClasses.org, http://www.phpclasses.org/browse/package/5652.html. Please use class from PHPClasses.org for bug fixed latest version.

I-Blood profile badge ready to use

5 August, 2009 (17:03) | Bangladesh, I-Blood, PHP, programming, web, Web Services | 1 comment

Tags: , , ,


I-Blood, is a social network for blood.

I-Blood offers donor profile for every member. Which is still in improvement.

Profile badge image for i-blood beta version is available now. Here is the image:

i-blood profile badge image.

Here is the link to the image: http://beta.i-blood.com/img/i-blood-badge.gif

Here is the sample code widget for placing the badge on your blog:

<p>
<a href="http://beta.i-blood.com/g/profiles/pub/45">
<img src="http://beta.i-blood.com/img/i-blood-badge.gif" border="0" alt="View Md. Rayhan Chowdhury's donor profile on I-Blood" width="160" height="38" />
</a>
</p>

just make a little change to the code above, change my profile link with your profile link and also my name with your name.

Convert a Multidimensional Array Into Single Dimension

28 June, 2009 (09:51) | PHP, programming, Reference | 9 comments

Tags: , , ,


RayArray is a array utility class.

I have wrapped three static functions for converting multidimensional configuration data. It is very much useful when working with configuration data. I have used this class in one of my project to store arbitrary configuration data just like windows registry data.

File: rayarray.php

<?php
/**
* RayArray arrays utility class
*
* This class provides configuration array handling funcionalities,
* may be usefull when dealing with configuration data.
*
* Usage: using this class you can convert a multidimensional configuration
* array into a single dimension array ready to store into sql table/ flat file.
*
* methods available are
*  - shorten() - static
*  - unshorten() - static
*  - subarray() - static
*
* @package     raynux
* @subpackage  raynux.lab.array
* @version     1.0
* @author      Md. Rayhan Chowdhury
* @email       ray@raynux.com
* @website     www.raynux.com
* @license     GPL
*/
class RayArray{
/**
 * Shorten an multidimensional array into a single dimensional array concatenating all keys with separator.
 *
 * @example array('country' => array(0 => array('name' => 'Bangladesh', 'capital' => 'Dhaka')))
 *          to array('country.0.name' => 'Bangladesh', 'country.0.capital' => 'Dhaka')
 *
 * @param array $inputArray, arrays to be marged into a single dimensional array
 * @param string $path, Default Initial path
 * @param string $separator, array key path separator
 * @return array, single dimensional array with key and value pair
 * @access public
 * @static
 */
static public function shorten(array $inputArray, $path = null, $separator = "."){
   $data = array();
   if (!is_null($path)) {
      $path = $path . $separator;
   }

   if (is_array($inputArray)) {
      foreach ($inputArray as $key => &$value) {
         if (!is_array($value)) {
            $data[$path . $key] = $value;
         } else {
            $data = array_merge($data, self::shorten($value, $path . $key, $separator));
         }
      }
   }

   return $data;
}

/**
 * Unshorten a single dimensional array into multidimensional array.
 *
 * @example array('country.0.name' => 'Bangladesh', 'country.0.capital' => 'Dhaka')
 *          to array('country' => array(0 => array('name' => 'Bangladesh', 'capital' => 'Dhaka')))
 *
 * @param array $data data to be converted into multidimensional array
 * @param string $separator key path separator
 * @return array multi dimensional array
 * @access public
 * @static
 */
static public function unshorten($data, $separator = '.'){
   $result = array();

   foreach ($data as $key => $value){
      if(strpos($key, $separator) !== false ){
         $str = explode($separator, $key, 2);
         $result[$str[0]][$str[1]] = $value;
         if(strpos($str[1], $separator)){
            $result[$str[0]] = self::unshorten($result[$str[0]], $separator);
         }
      }else{
         $result[$key] = is_array($value)?  self::unshorten($value, $separator) : $value;
      }
   }
   return $result;
}

/**
 * Get part of array from a multidimensional array specified by concatenated keys path.
 *
 * @example
 *          path = "0.name"
 *          data =
 *          array(
 *                  array('name' => array('Bangladesh', 'Srilanka', 'India', 'Pakistan')),
 *                  array('help' => 'help.php'),
 *                  'test' => 'value',
 *                  10 =>
 *          false)
 *          will return array('Bangladesh', 'Srilanka', 'India', 'Pakistan')
 * @param string $path
 * @param array $data
 * @param string $separator path separator default '.'
 * @return mixed and return NULL if not found.
 * @access public
 * @static
 */
static public function subarray($path, &$data, $separator = '.') {
   if (strpos($path, $separator) === false) {
      if (isset($data[$path])) {
         return $data[$path];
      }
   } else {
      $keys = explode($separator, $path, 2);
      if (array_key_exists($keys[0], $data)) {
         return self::subarray($keys[1], $data[$keys[0]], $separator);
      }
   }
}
}
?>

Please drop me a line if you find this class useful or you have a different opinion.

Http Client Class for PHP development

13 June, 2009 (13:01) | PHP, programming, Reference | 9 comments

Tags: , , , ,


RayHttp, A Simple Http Client Class for PHP Development.

This class is designed to provide quick http reqest method to access external website. A CURL alternative to php native file_get_contents method. It can work without any configuration and can be called anywhere is your application using singleton design pattern. Unlike other Http client class in php, this is lightweight, simple and easy to use and configure. If you need more functionality you can extend the class. CURL request is fully customizable through setCurlOptions() method.

This class is suitable for those project which is not built on a PHP Framework. Usually all frameworks provide a built in Http Client Object.

Features:

- General purpose http request class.
- Supports GET & POST request Method.
- For GET Request both CURL & PHP native file_get_contents are available.
- By default CURL is used for GET Request.
- Easily configurable & can work without any configuration.
- Simple & Easy to use from anywhere in your application with a single line of code.
- Request through CURL fully configurable with all possible curl options, so it’s up to you.
- Encode given URL Automatically, may be disabled.
- Supports POST requests with a user defined array or serialised string of form values.
- Supports GET requests with a user defined parameter array.
- Support Singleton pattern
- Support Custom CURL request, may be used to extends functionality.
- Light Weight

Methods Available (This class provides):

- get()
- post()
- curlExecute()
- encodeUrl()

Class:

File: rayhttp.php

<?php
/*	SVN FILE: $Id: rayhttp.php 113 2008-06-15 04:30:19Z rayhan $	 */
/**
 * HTTP Client Class.
 *
 * A basic HTTP Client desinged for php developer.
 * - CURL
 * - Native php method
 *
 *	PHP Version 5
 *
 *
 *	@copyright		Copyright 2006-2008, Md. Rayhan Chowdhury
 *	@package		raynux
 *	@subpackage		raynux.lab.http
 * 	@since			version 1.0
 *	@version		$Revision: 113 $
 * 	@modifiedby		$LastChangedBy: rayhan $
 *	@lastModified	$Date: 2008-06-15 10:30:19 +0600 (Sun, 15 Jun 2008) $
 *	@author			$Author: rayhan $
 *	@url			$HeadURL: http://localhost/svn/raynux/trunk/labs/rayhttp.php $
 *	@website		www.raynux.com
 *  @license 		GPL
 */

/**
 * HTTP Client Class.
 *
 * A basic HTTP Client desinged for php developer.
 * - CURL
 * - Native php method
 *
 *
 * @todo add utf-8 conversion.
 * @todo add plugins functionality
 *
 *
 * @package raynux
 * @subpackage raynux.lab.http
 * @version 1.0
 * @since version 1.0
 * @author Md. Rayhan Chowdhury
 */
class RayHttp{

	/**
	 * Hold runtime instance of self
	 *
	 * @var array of self instances
	 * @access private
	 * @static
	 */
	static private $__instances;

	/**
	 * Curl Instance
	 *
	 * @var object Curl instance
	 * @access protected
	 */
	protected 	$_curlInstance = null;

	/**
	 * Default configuration for the crawler.
	 *
	 * @var array
	 * @access private
	 */
	private 	$__defaultConfigs = array(
                    'client' => 'curl',
                    'encodeUrl' => true,
                    'curlOptions' => array(
                        CURLOPT_SSL_VERIFYPEER => 0,
                        CURLOPT_RETURNTRANSFER => 1,
                        CURLOPT_FOLLOWLOCATION => 1,
                        CURLOPT_ENCODING => "",
                        CURLOPT_USERAGENT => "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.0.5) Gecko/2008120121 Firefox/3.0.5",
                        CURLOPT_COOKIESESSION => 1,
                        CURLOPT_AUTOREFERER => 1,
                        CURLOPT_CONNECTTIMEOUT => 120,
                        CURLOPT_AUTOREFERER => 120,
                        CURLOPT_TIMEOUT => 120,
                        CURLOPT_MAXREDIRS => 10,
                        CURLOPT_COOKIEFILE => 'cookiefile',
                        CURLOPT_COOKIEJAR => 'cookiefile',
                    ),
                );

	/**
	 * Hold runtime configuration.
	 *
	 *
	 * @var array
	 * @access protected
	 */
	protected 	$_configs = array();

	/**
	 * Class Constructor
	 *
	 * @param array $configs
	 * @access public
	 * @return unknown
	 */
	function __construct($configs = array()){
		if (!empty($configs)) {
			$this->setOptions($configs);
		} else {
			$this->setOptions($this->__defaultConfigs);
		}
	}

	/**
	 * Configure the class.
	 *
	 * @param array $configs, configuration data.
	 * @return unknown
	 * @access public
	 */
	public function &setOptions($configs){
		$this->_configs = array_merge($this->__defaultConfigs, $configs);

		return $this;
	}

	/**
	 * Get Curl Instance.
	 *
	 * @return object curl instance
	 * @access protected
	 */
	protected function &_getCurlInstance() {
		if ($this->_curlInstance == null) {
			$this->_curlInstance = curl_init();
			$this->setCurlOptions($this->_configs['curlOptions']);
		}
		return $this->_curlInstance;
	}

	/**
	 * Set Curl Options from array
	 *
	 * @param array $options
	 * @return object | this
	 * @access public
	 */
	public function &setCurlOptions($options = array()) {
		$c = $this->_getCurlInstance();
		if (function_exists('curl_setopt_array')) {
			curl_setopt_array($c, $options);
		} else {
			foreach ($options as $key => $value) {
				curl_setopt($c, $key, $value);
			}
		}
		return $this;
	}

	/**
	 * Execute curl library function.
	 *
	 * @param string $url
	 * @param string $method, http method, 'get' or 'post'
	 * @param string|array $postFields, form data
	 * @return string | curl response object
	 * @access public
	 */
	public function curlExecute($url, $method = 'get', $postFields = null){
		$c = $this->_getCurlInstance();
		if ($method === 'get') {
			$this->setCurlOptions(array(CURLOPT_URL => $url,
                                        CURLOPT_POST => false,
                                        CURLOPT_HTTPGET => 1));

		} elseif ($method === 'post') {
			$this->setCurlOptions(array(CURLOPT_URL => $url,
                                        CURLOPT_POST => true,
                                        CURLOPT_HTTPGET => 0,
                                        CURLOPT_POSTFIELDS => $postFields));

		} else {
			$this->setCurlOptions(array(CURLOPT_URL => $url));

		}
		return curl_exec($c);
	}

	/**
	 * Encode url with urlencode function for unencoded character.
	 *
	 * @param string $url urls to be encoded.
	 * @param string $callback function name as callback function, 'urlencode' or 'raw_urlencode'
	 * @return string encoded url.
	 * @access public
	 */
	public function encodeUrl($url, $callback = 'urlencode') {
		if ($pathOfset = strpos($url, '/', (strpos($url, '://') + 3))) {

			extract(parse_url($url));

			$path = implode('/', array_map($callback, explode('/', $path)));
			$url = substr($url, 0, $pathOfset) . $path;

			if (!empty($query)) {
				parse_str($query, $query);
				$query = http_build_query(array_map($callback, $query));
				$query = preg_replace('@(\=($|(&)))@is', '\3', $query);			// remove tailing = sign from empty variable.
				$url = $url . "?" . $query;
			}
		}

		return $url;
	}

    /**
     * Get Self Instance.
     *
     * @param string $name, name of the instance, default value is 'default'
     * @param array $configs, configuration array for the instance
     * @return object, self instance
	 * @access public
     * @static
     */
    static public function &getInstance($name = 'default', $configs = array()){
    	if (is_null(self::$__instances[$name])) {
    		self::$__instances[$name] = new self($configs);
    	}
    	return self::$__instances[$name];
    }

	/**
	 * Get url contents using GET MEthod.
	 *
	 * @param string $url
	 * @param string|array $getData, get data in serialized string or array format.
	 * @return string
	 * @access public
	 */
    public function get($url, $getData = null){
    	if (!is_null($getData)) {
    		if (is_array($getData)) {
    			$getData = http_build_query($getData);
    		}
    		if (strpos($url, '?') === false) {
    			$url .= '?';
    		}
    		$url .= $getData;
    	}

    	if ($this->_configs['encodeUrl']) {
    		$url = $this->encodeUrl($url);
    	}

    	if ($this->_configs['client'] === 'php') {
    		return file_get_contents($url);
    	}
    	return $this->curlExecute($url);
    }

    /**
     * Get URL contents using POST method.
     *
     * @param string $url
     * @param string|array $postData, form data in serialized string or array format.
     * @return string
     * @access public
     */
    public function post($url, $postData = null) {
    	if (is_array($postData)) {
    		$postData = http_build_query($postData);
    	}

    	if ($this->_configs['encodeUrl']) {
    		$url = $this->encodeUrl($url);
    	}

    	return $this->curlExecute($url, 'post', $postData);
    }
}

Usage Example:
File: example.php

<?php
/**
 * HTTP Client Class Example Script.
 *
 * Example of RayHttp Class Object.
 *
 *	PHP Version 5
 *
 *
 *	@copyright		Copyright 2006-2008, Md. Rayhan Chowdhury
 *	@package		raynux
 *	@subpackage		raynux.lab.http
 * 	@since			version 1.0
 *	@version		$Revision: 113 $
 * 	@modifiedby		$LastChangedBy: rayhan $
 *	@lastModified	$Date: 2008-06-15 10:30:19 +0600 (Sun, 15 Jun 2008) $
 *	@author			$Author: rayhan $
 *	@url			$HeadURL: http://localhost/svn/raynux/trunk/labs/example.php $
 *	@website		www.raynux.com
 *  @license 		GPL
 */

/**
 * Load the http client.
 */
require_once("rayhttp.php");

/**
 * METHOD GET.
 */

/**
 * Example 1
 *
 * using default configuration
 * default method is curl.
 * use as a singleton object.
 */
$content = RayHttp::getInstance()->get("http://google.com");
$content = RayHttp::getInstance()->get("http://google.com/search", array('q' => 'rayhttp'));
$content = RayHttp::getInstance()->get("http://google.com/search?q=rayhttp");

/**
 * Example 2
 *
 * using default configuration but using php native file_get_contetns method.
 * use as a singleton object.
 * static method.
 */
$content = RayHttp::getInstance()->setOptions(array('client' => 'php'))->get("http://google.com");
$content = RayHttp::getInstance()->setOptions(array('client' => 'php'))->get("http://google.com/search", array('q' => 'rayhttp'));
$content = RayHttp::getInstance()->setOptions(array('client' => 'php'))->get("http://google.com/search?q=rayhttp");

/**
 * Example 3
 *
 * Take Instance Of the object
 */
$http = new RayHttp();
$content = $http->get("http://google.com");
$content = $http->get("http://google.com/search", array('q' => 'rayhttp'));
$content = $http->get("http://google.com/search?q=rayhttp");

/**
 * METHOD POST.
 */

/**
 * Example 4
 *
 * using default configuration
 */
$content = RayHttp::getInstance()->post("http://example.com/", array('name' => 'rayhttp', 'location' => 'dhaka, bangladesh'));

/**
 * Multiple Instance & Configuration.
 */
RayHttp::getInstance('default', $configs);
RayHttp::getInstance('default2', $configs);

$http = RayHttp::getInstance(); // get default instance
$http2 = RayHttp::getInstance('default2'); // get default2 instance

$http3 = RayHttp::getInstance('default3', $configs); // get default 3 instance
$http3->setOptions($configs); // reconfigure default3 instance;

/**
 * Specify Proxy
 */
RayHttp::getInstance('c')->setCurlOptions(array(CURLOPT_PROXY => '172.19.79.1:3128'))->get("http://www.google.com");

Rate this class at phpclasses.org: http://www.phpclasses.org/rayhttpclient

« Older entries