Tuesday, December 30, 2008

Php - Human readable PHP password generator

Human readable PHP password generator



<?
/*
Programmed by Christian Haensel, christian@chftp.com, LINK1http://www.chftp.comLINK1
Exclusively published on weberdev.com.
If you like my scripts, please let me know or link to me.

You may copy, redistirubte, change and alter my scripts as long as this information remains intact
*/


$length        =    6; // Must be a multiple of 2 !! So 14 will work, 15 won't, 16 will, 17 won't and so on

// Password generation
   
$conso=array("b","c","d","f","g","h","j","k","l",
   
"m","n","p","r","s","t","v","w","x","y","z");
   
$vocal=array("a","e","i","o","u");
   
$password="";
   
srand ((double)microtime()*1000000);
   
$max = $length/2;
    for(
$i=1; $i<=$max; $i++)
    {
   
$password.=$conso[rand(0,19)];
   
$password.=$vocal[rand(0,4)];
    }
   
$newpass = $password;
// ENDE Password generation
   
echo $newpass."<p>";
?>


Php - Recursive Directory Listing

Recursive listing of all the files / directories in directory. Includes security measure to prevent users from browsing the parent directory.


<?php
// Get the filename of the current page
$PHP_SELF = $_SERVER['PHP_SELF'];
function
recursiveReadDir($path){
    global
$PHP_SELF, $basePath, $baseUrl;
   
// Open the directory for reading
   
$dir = @opendir("$basePath/$path");
    if(
$dir){
        echo
"<b>[<a href='$PHP_SELF?path=$path'>DIR </a>] " . basename($path) . "</b>\n";
        echo
"<ul>\n";
       
// Loop through each directory
       
while ($file = readdir($dir)) {
            if(
$file == '.' || $file == '..')continue;
            elseif(
is_dir("$basePath/$path/$file")){
               
// Current file is a directory, so read content of the new directory
               
echo "<li>\n";
               
recursiveReadDir("$path/$file");
                echo
"</li>";
            }else{
                echo
"<li>[FILE] <a href=\"$baseUrl$path/$file\">$file</a></li>\n";
            }
        }
       
closedir($dir);       
        echo
"</ul>\n";
    }else{
        echo
"Unable to open directory. Click <a href='$curFile'>here</a> to go back.";
    }
}

?>
<html>
<head>
<title>Directory Browser</title>
</head>
<body>
<?php
// The base path for browsing
$basePath = realpath('/var/www/vhosts/mydomain.com/httpdocs/files');
// Url corresponding to base path
$baseUrl = 'http://www.mydomain.com/files';
// Get the location
$path  = empty($_GET['path']) ? '.' : $_GET['path'];
// Find the absolute path to the location
$path = realPath("$basePath/$path");
// If the location is below the base url, exit
// This prevents users from browsing parent directories using ..
if(eregi('^' . preg_quote($basePath), $path)){
   
// Get the actual relative path from the basepath
   
$curPath = substr($path, strlen($basePath) + 1);
   
$arPath = explode('/', str_replace('\\', '/', $curPath));
   
$path = '';
   
   
// Bread Crumb for navigation
   
echo "<div><a href='$PHP_SELF'>Home</a>";
    if(empty(
$arPath[0]))unset($arPath[0]);
    foreach(
$arPath as $p){
       
$path .= "/$p";
        echo
" > <a href='$PHP_SELF?path=$path'>$p</a>";
    }
    echo
'</div>';
   
   
// Recursively list the directory
   
recursiveReadDir($curPath);
}else{
    echo
"You are not allowed to access this file directly. Click <a href='$PHP_SELF'>here</a> to go back.";
}

?>     
</body>
</html>

Saturday, December 20, 2008

PHP - Reverse a given number

Simple example for reversing a given number.


<?php
$num
=6541020;
$revnum=0;
do{
   
$revnum=($revnum *10)+($num % 10);
   
$num=(int)($num / 10 );
}while(
$num>0);
echo
$revnum;
?>

PHP- PDO Wrapper Class

An easy to use PDO wrapper class. Includes methods like

PDO::getRecord()
PDO::insertRecord()
PDO::updateRecord()
PDO::getQuery()

for easy coding and better error control. Please let me know your comments.

<?php
class extendedPDO extends PDO{
    private
$arQuery = array();
   
/*
    Parameters same as original PDO::exec
    */   
   
public function exec($statement){
        if(!empty(
$statement)){
            try{
               
$result = parent::exec($statement);
                if(
$result === FALSE)$this->triggerError();
            }catch(
PDOException $e){
               
$this->triggerError($e);
            }
           
$this->arQuery[] = $statement;
            return
$result;
        }else{
            return
FALSE;
        }
    }
   
/*
    Parameters same as original PDO::query
    */
   
public function query($statement, $fetchMode = null, $objORClassnameORColNo = null, $ctorargs = null){
        if(!empty(
$statement)){
            try{
               
$this->stmt = parent::query($statement, $fetchMode, $objORClassnameORColNo, $ctorargs);
               
$this->arQuery[] = $statement;
                if(
$this->stmt === FALSE)$this->triggerError();
            }catch(
PDOException $e){
               
$this->triggerError($e);
            }
            return
$this->stmt;
        }else{
            return
FALSE;
        }
    }
   
/*
    Function to return previously executed query
    @param - The index of the query. If none is provided, then last query is returned
    */
   
public function getQuery($idx = null){
        if(empty(
$this->arQuery))return false;
        if(
is_null($idx)){
           
$idx = count($this->arQuery) - 1;
        }
        return
$this->arQuery[$idx];
    }
   
/*
    Function to retrieve existing row(s) from the database
    @param $tblName - DB Table Name
    @param $conditions - Condition for updation as associative array(eg. array('id' => ))
    @param $values - the value to be inserted as an associative array (eg. array('id' => 1, 'uid' => '007', 'name' => 'James Bond'))
    @param $limit - Number of rows to retrieve. If $limit is null, then all matching rows are retrieved. If $row is an array, say array( 50, 10)
                    Then rows 50 - 60 will be returned. If limit is 1, then result is returned as an associative array
    */
   
function getRecord($tblName, $conditions, $limit = 1){
       
$whereSql = $this->_getWhereSQL($conditions);
       
$limitSql = $this->_getLimitSQL($limit);
       
$stmt = $this->query("SELECT * FROM $tblName $whereSql $limitSql");
        if(
$stmt !== FALSE && $limit == 1){
            return
$stmt->fetch(PDO::FETCH_ASSOC);
        }else{
            return
$stmt;
        }
    }
   
/*
    Function to insert a new row into the database
    @param $tblName - DB Table Name
    @param $values - the value to be inserted as an associative array (eg. array('id' => 1, 'uid' => '007', 'name' => 'James Bond'))
    */
   
public function insertRecord($tblName, $values) {
       
$keys = array_keys($values);
       
$fields = '(`' . implode('`, `', $keys) . '`)';
       
$values = '(' . implode(', ', array_map(array($this, 'quote'), $values)) . ")";
        return
$this->exec("INSERT INTO `$tblName` $fields VALUES $values");
    }
   
/*
    Function to update an existing row in the database
    @param $tblName - DB Table Name
    @param $conditions - Condition for updation as associative array(eg. array('id' => ))
    @param $values - the value to be inserted as an associative array (eg. array('id' => 1, 'uid' => '007', 'name' => 'James Bond'))
    @param $limit - Number of rows to update. If $limit is null, then all matching rows are updated. If $row is an array, say array( 50, 10)
                    Then rows 50 - 60 will be updated
    */
   
public function updateRecord($tblName, $conditions, $values, $limit = 1) {
       
$fields = $this->_getValues($values);
       
$whereSql = $this->_getWhereSQL($conditions);
       
$limitSql = $this->_getLimitSQL($limit);
        return
$this->exec("UPDATE `$tblName` SET $fields $whereSql $limitSql");
    }
    function
triggerError($e = FALSE){
       
// Here do your error management procedures
        // You may sent a notification mail with the error details
       
echo "<br/><b>Database Error:</b> ";
        if(
$e){
            echo
$e->getMessage();
        }else{
           
$errorInfo = $this->errorInfo();
            echo
"[$errorInfo[1]] $errorInfo[2]";
        }
        exit;
    }
    private function
_getValues($values = null){
        if(
is_null($values)){
           
$values = '';
        }elseif(
is_array($values)){
           
$arField = array();
            foreach(
$values as $field => $value){
               
$value = $this->quote($value);
               
$arField[] = "`$field` = $value";
            }
           
$values = implode(', ', $arField);
        }else{
           
$values = '';
        }   
        return
$values;
    }
    private function
_getWhereSQL($condition){
       
//$condition = $this->_getCondition($condition);
       
if(is_null($condition)){
           
$values = '';
        }elseif(
is_array($condition)){
           
$arField = array();
            foreach(
$condition as $field => $value){
               
$value = $this->quote($value);
               
$arField[] = "`$field` = $value";
            }
           
$condition = 'WHERE ' . implode(' AND ', $arField);
        }else{
           
$condition = '';
        }
        return
$condition;
    }
    private function
_getLimitSQL($limit = null){
        if(
is_null($limit)){
           
$limit = '';
        }elseif(
is_array($limit)){
           
$limit = "LIMIT $limit[0], $limit[1]";
        }else{
           
$limit = "LIMIT $limit";
        }
        return
$limit;
    }
}

?>





DB Schema

CREATE TABLE `test`.`weber_test` (
`id` INT( 5 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`title` VARCHAR( 255 ) NOT NULL ,
`author` VARCHAR( 50 ) NOT NULL ,
`price` VARCHAR( 5 ) NOT NULL
) ENGINE = MYISAM




example usage

<?php
$dbType
= 'mysql';
$dbHost = 'localhost';
$dbUser = 'root';
$dbPass = '';
$dbName = 'test';
$pdo = new extendedPDO("$dbType:host=$dbHost;port=4040;dbname=$dbName", $dbUser, $dbPass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

$pdo->insertRecord('weber_test', array('title' => 'Around the World in 80 Days', 'author' => 'Julie Verne', 'price' => '$90'));
$id = $pdo->lastInsertId();
$pdo->updateRecord('weber_test', array('id' => $id), array('author' => 'Jules Verne', 'price' => '$' . mt_rand(0, 500) ));
$record = $pdo->getRecord('weber_test', array('id' => $id));

print <<<HERE
Inserted Data<br/>
ID : $id<br/>
Title :
{$record['title']}<br/>
Author :
{$record['author']}<br/>
Price :
{$record['price']}<br/><br/>
HERE;

$stmt = $pdo->getRecord('weber_test', null, null);
if(
$stmt){
    echo
'<table>';
   
$stmt->setFetchMode(PDO::FETCH_ASSOC);
    while(
$record = $stmt->fetch()){
        echo
"<tr><td>{$record['id']}</td><td>{$record['title']}</td><td>{$record['author']}</td><td>{$record['price']}</td></tr>";
    }
    echo
'</table>';
}
?>

PHP - Using PHP for XSLT transformations

Templating using XSL Transformation is a technique that is becoming more and more popular. PHP 5 has support for XSLT. But the best thing about using XSLT in PHP is that, php supports calling native functions in PHP from the XSL template. This increases the power of XSL transformation by several folds. Here is an example on how to transform xml to xhtml using php and use native php functions.


<?php
// Set default time zone
date_default_timezone_set('Asia/Calcutta');
$xmlStr = <<<STR
<Profiles>
<Profile>
  <id>1</id>
  <name>john doe</name>
  <dob>188677800</dob>
</Profile>
<Profile>
  <id>2</id>
  <name>mark antony</name>
  <dob>79900200</dob>
</Profile>
<Profile>
  <id>3</id>
  <name>neo anderson</name>
  <dob>240431400</dob>
</Profile>
<Profile>
  <id>4</id>
  <name>mark twain</name>
  <dob>340431400</dob>
</Profile>
<Profile>
  <id>5</id>
  <name>frank hardy</name>
  <dob>390431400</dob>
</Profile>
</Profiles>
STR;
$xslStr = <<<EOB
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:php="http://php.net/xsl" exclude-result-prefixes="php">
<xsl:output method="xml" encoding="utf-8" indent="yes" omit-xml-declaration="yes" standalone="no" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>
<xsl:template match="/">
  <html>
    <head>
      <title>User Profiles</title>
    </head>
    <body>
      <h1>Using PHP Functions in XSLT</h1>
      <table cellspacing="1" cellpadding="5" border="1">
         <caption>User Profiles</caption>
         <tr><th>ID</th><th>Name</th><th>Date of Birth</th></tr>
         <xsl:for-each select="/Profiles/Profile">
         <tr>
            <td><xsl:value-of select="id"/></td>
            <td><xsl:value-of select="php:function('ucwords', string(name))"/></td>
            <td><xsl:value-of select="php:function('date', 'jS M, Y', number(dob))"/></td>
         </tr>
         </xsl:for-each>
      </table>
    </body>
  </html>
</xsl:template>
</xsl:stylesheet>
EOB;

$xmlDoc = new DOMDocument();
$xmlDoc->loadXML($xmlStr);

$xslDoc = new DOMDocument();
$xslDoc->loadXML($xslStr);

$xsltProcessor = new XSLTProcessor();
$xsltProcessor->registerPHPFunctions();
$xsltProcessor->importStyleSheet($xslDoc);
echo
$xsltProcessor->transformToXML($xmlDoc);
?>

MySQL - Query Caching

MySQL supports a cool feature called Query caching. ie, MySQL can be configured to cache the result set of a select statement. After that, whenever the query is executed, the data is fetched from the memory, rather than searching the database. When one of the tables in the query is updated, the cached query is invalidated.

When the number of select statements is very large than the number of update statements, this can produce a significant change in performance. The best thing about MySQL Query Caching is that you don't have to make any changes to your query to activate this feature (there is an alternate method that selectively caches the query, which requires changing the query).

How to enable Query Caching.

If the number of SELECT queries is much higher than the number of update statements, then this is the best method as this requires no change in your program.
Edit your my.cnf file(usually located at /etc/my.cnf).

$ vi /etc/my.cnf

Under the section [mysqld] add

# Enable Mysql Query Caching
# 0 => Caching is disabled
# 1 => Caching is enabled for all queries
# 2 => This requires adding the keyword SQL_CACHE to the queries that are to be cached

query_cache_type = 1

# This is the total memory in bytes allocated for Query Caching
query_cache_size = 32000000

# This is the maximum permitted size in bytes for a single result set. If the size of the result set is greater than this, then the query is not cached

query_cache_limit = 1000000

Now restart mysql. In most of the unix systems, the following will work
$ /etc/init.d/mysqld restart

and in Mac, try this
$ /Library/StartupItems/MySQLCOM/MySQLCOM restart



Thats it. Now mysql query caching is enabled for all your queries. To see the status of caching login to mysql

$ mysql -u username -p password

If your login was successful, you can see the mysql prompt. Type the following query in the mysql prompt


mysql> SHOW VARIABLES LIKE 'query%';
That will show a table with the values you specified in the my.cnf file
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_alloc_block_size       | 8192     |
| query_cache_limit            | 1000000  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 32000000 |
| query_cache_type             | ON       |
| query_cache_wlock_invalidate | OFF      |
| query_prealloc_size          | 8192     |
+------------------------------+----------+

Now see the status of the query caching enter
mysql> SHOW STATUS LIKE 'QC%';
That will show you a table like the one below
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 31982456 |
| Qcache_hits             | 0        |
| Qcache_inserts          | 0        |
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 2        |
| Qcache_queries_in_cache | 0        |
| Qcache_total_blocks     | 1        |
+-------------------------+----------+
8 rows in set (0.00 sec)

now exit from mysql and perform an apache benchmark
$ ab -n 50 -c 5 http://yoursite/

Now login back into mysql
$ mysql -u username -p password
mysql > SHOW STATUS LIKE 'QC%';
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 31863864 |
| Qcache_hits             | 778      |
| Qcache_inserts          | 17       |
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 109      |
| Qcache_queries_in_cache | 17       |
| Qcache_total_blocks     | 39       |
+-------------------------+----------+
8 rows in set (0.00 sec)



Qcache_inserts shows the number of queries inserted into the cache and Qcache_hits shows the number of requests served from the cache.

Btw, I hope you saw the result of the apache benchmark :). This was the result I obtained
Percentage of the requests served within a certain time (ms)
50% 151
66% 173
75% 200
80% 389
90% 4471
95% 4507
98% 4507
99% 4507
100% 4507 (longest request)

4507 ms was for the first query, when the cache was not available and 151 ms was for the cached request.


BTW, DON'T USE THIS METHOD IF THE FREQUENCY OF UPDATION IS EQUIVALENT TO THE FREQUENCY OF SELECTION, BECAUSE THE OVERHEAD CAUSED BY THE CACHE INVALIDATION WILL DEGRADE THE PERFORMANCE.

PHP Cookies - Simple cookie write/read methods that allow basic encryption

Saving and retrieving cookies is extremely simple in PHP using the setcookie() function and $_COOKIE super global variable. But what if you do no want to let the user see the data, let alone alter it? Here is simple cookie write/read methods that allow basic encryption. To delete a cookie, give a negative life


<?php
// Global Cookie Life in seconds, can be overridden in the function call
$cookieLife = 2592000; // 30days

// Global key for encryption, can be overridden in the function call
$encryptKey = '';//'mysecretkey';

/*
@param $name - Name of cookie
@param $val - Value of the cookie
@param $time - Life of the cookie in seconds
@param $key - Key for encrypting cookie
@return TRUE on success else FALSE
*/
function writeCookie($name, $val, $time = null, $key = null){
   
$time = is_null($time) ? $GLOBALS['cookieLife'] : $time;
   
$key = is_null($key) ? $GLOBALS['encryptKey'] : $key;
   
$val = gzcompress(serialize($val) . $key);
   
$val = urlencode(base64_encode($val));

   
// Save the cookie if header is not already sent
   
if(!headers_sent()) {
        return
setcookie($name, $val, time() + $time, '/');
    }else{
        return
FALSE;
    }
}
/*
@param $name - Name of Cookie
@param $key - Key to decrypt, should be same as the one used for encrypting
@param $default - Default value, if the specified cookie does not exist
*/
function readCookie($name, $key = null, $default=null){
    if(isset(
$_COOKIE[$name])){
       
$key = is_null($key) ? $GLOBALS['encryptKey'] : $key;
       
$val = $_COOKIE[$name];
       
$val = base64_decode(urldecode($val));
       
$val = substr(gzuncompress($val), 0, strlen($val) - strlen($key));
       
$val = unserialize($val);
        return
$val;
    }else{
        return
$default;
    }
}
?>




usage example

<?php
// Counter using global key
$counter1 = readCookie('counter1');
$counter1 = is_null($counter1) ? 0 : $counter1;
$str = "Counter 1 - $counter1 (increments by 1)<br/>";
writeCookie('counter1', ++$counter1);

// Counter with key passed during function call
$counter2 = readCookie('counter2', 'mykey');
$counter2 = is_null($counter2) ? 0 : $counter2;
$str .= "Counter 2 - $counter2 (Increments by 2)<br/>";
$counter2 += 2;
writeCookie('counter2', $counter2, null, 'mykey');

// Read cookie, with default value if the specified cookie does not exist
$counter3 = readCookie('counter3', null, 1);
$str .= "Counter 3 - $counter3 (Doubles)<br/>";
$counter3 *= 2;
writeCookie('counter3', $counter3);

echo
$str;

// Invalid Cookie, does not work because output already started at previous line
// If you have output buffering enabled, it will work though
$counter = readCookie('counter', null, 1);
$str .= "Counter Invalid - $counter (Remains 1 always)<br/>";
$counter *= 2;
echo
"Counter Invalid - $counter (Supposed to double, but always shows 2 since header already sent)";
writeCookie('counter', $counter);
?>

Thursday, December 11, 2008

Php - List list of files by date of creation

Run this php code to get list of files

list directory files


function folderlist(){
$startdir = './uploadg/';
$ignoredDirectory[] = '.';
$ignoredDirectory[] = '..';
$i=1;
if (
is_dir($startdir)){
if (
$dh = opendir($startdir)){
while ((
$folder = readdir($dh)) !== false){
if (!(
array_search($folder,$ignoredDirectory) > -1)){
if (
filetype($startdir . $folder) == "dir"){
$directorylist[$startdir . $folder]['name'] = $folder;
$directorylist[$startdir . $folder]['path'] = $startdir;
}
}
}
closedir($dh);
}
}
return(
$directorylist);
}

$folders = folderlist();
foreach (
$folders as $folder){
$path = $folder['path'];
$name = $folder['name'];
$i++;
echo
"$i. $name

"
;


}
?>