Posts Tagged ‘php’

Building PNG Images

Jeudi, septembre 18th, 2008

Did you ever try to build a png image (with a programming language, not an image editor)?  A lot of code sample are available on the internet.  But most if not all are using libpng or some high level libraries like gd.

But what happend if you can’t install libraries on the system where you’re working?  Ever thing about building an image from scratch?  Here is what I do in PHP.

This isn’t the most performant code, but at least it generate a valid PNG image without any non standard libraries.   (Some one could say that zlib or crc are php external libs.. but I haven’t see any php distribution whitout them in a while!)

<?php
/*
* Title: PNG Image Generation
* Author: Jean-Luc Cyr
* Date: 2008-09-17
* License: GNU GPL2
* Description: Generate a simple PNG image
* directly in PHP without using external libs
* like GD.
*/
 
header("content-type: image/png");
 
function long2string($long)
{
$string = chr(($long&0xFF000000)>>24).
chr(($long&0xFF0000)>>16).
chr(($long&0xFF00)>>8).
chr(($long&0xFF)>>0);
return $string;
} // long2string()
function build_png($matrix, $w, $h)
{
////////////////////////////////////////////////////////////////
//PNG Header
$image = chr(0x89).chr(0x50).chr(0x4E).chr(0x47);
$image .= chr(0x0D).chr(0x0A).chr(0x1A).chr(0x0A);
 
////////////////////////////////////////////////////////////////
//Header Chunk
 
//Chunk type
$chunk = "IHDR";
//Chunk data
//Width
$data = long2string($w);
//Height
$data .= long2string($h);
//Depth
$data .= chr(8); //Bits per sample
//Color Type
$data .= chr(2); //RGB
//Compression method
$data .= chr(0);
//Filter method
$data .= chr(0);
//Interlaced method
$data .= chr(0);
 
$crc = crc32($chunk.$data);
//Add length at start
$chunk = long2string(strlen($data)).$chunk.$data;
//Add CRC at the end
//Dump chunk
$chunk = $chunk.long2string($crc);
$image .= $chunk;
 
////////////////////////////////////////////////////////////////
//Data Chunk
 
//Chunk type
$chunk = "IDAT";
//Data (2x2 rgb 8bits)
$s = 3; //samples per pixels
#$matrix  ="\0\0\0\0\0\0\0\0\0";
#$matrix .="\0\0\0\0\0\0\0\0\0";
#$matrix .="\0\0\0\0\0\0\0\0\0";
// No filter so add 0 to beginning of each scan line
$datas = '';
for($c=0; $c<$h; $c++)
$datas .= "\0". substr($matrix,$c*($w*$s),($w*$s));
// Compress Data
#$zdata = gzencode($data,9,FORCE_DEFLATE);
#$zdata = gzdeflate($data,0);
$zdata = gzcompress($datas,0);
// Calculate CRC
$crc = crc32($chunk.$zdata);
// Add length at start
$l = strlen($zdata);
$chunk = long2string($l).$chunk.$zdata;
// Add CRC at the end
$chunk = $chunk.long2string($crc);
$image .= $chunk;
 
////////////////////////////////////////////////////////////////
//End Chunk
 
// Chunk type
$chunk = "IEND";
// Data
$data = "";
// Calculate CRC
$crc = crc32($chunk);
// Add length at start
$chunk = long2string(strlen($data)).$chunk.$data;
// Add CRC at the end
$chunk = $chunk.long2string($crc);
$image .= $chunk;
 
// Send out the image
echo $image;die();
} // build_png()
////////////////////////////////////////////////////////////////
// Demo code
 
// Build a simple image matrix
// 256 x 256 x 8rgb
 
$w=256; // width
$h=256; // height
$s=3;   // 3 x 8 bits samples per pixel (8bits rgb)
for($x=0; $x<$h; $x++)
for($y=0; $y<$w; $y++)
//    for($z=0; $z<$s; $z++) //Ordered R G B
$matrix .=
chr( ( (($y/64)<1) && (($y/64)>0) )?$x:0 ). // R
chr( ( (($y/64)<2) && (($y/64)>1) )?$x:0 ). // G
chr( ( (($y/64)<3) && (($y/64)>2) )?$x:0 ); // B
 
build_png($matrix,$w,$h);
die();
 
////////////////////////////////////////////////////////////////
// Hex dump image for debugging
 
for ($x=0; $x<strlen($image); $x++) {
printf("%02X ",ord($image[$x]));
if ((($x+1)%16)==0)
printf("<br/>");
}

ASN.1/DER/BER PHP

Mercredi, février 13th, 2008

Je vous ai parlé dernièrement de ASN.1. Voici un petit parseur de base en PHP

 
//Title: Simple PHP BER/DER/ASN.1 basic decoder
//Author: Jean-Luc Cyr
//Date: 2008-02-13
//Desc: Simple BER Printable string dumper
//	read BER data from a file
 
// Set input filename
$filename = 'o';
// Set max number of tag to parse (0 = no limit)
$limit = 0;
 
//Open data file
$f = fopen($filename,'rb');
//Set read tag number to 0
$c=0;
//While not end of file
while(!feof($f))
{
    //Read first block data type
    $type = ord(fread($f,1));
    if ($type==0)
      break;
    //Read first len block
    $len = ord(fread($f,1));
    if ($len==0)
      break;
    $le = 0;
    //If first bit of len is set (1)
    //we have a multiple bit len to read
    if (($len&128)==128)
    {
        echo "Big Len ".($len&127)." Bytes\r\n";
        for ($i = 0; $i < ($len&127); $i++)
          $le = $le * 256 + ord(fread($f,1));
        $len = $le;
    }
    //Findout data type (first 2 bits)
    $cl = ($type & (128+64) ) >> 6;
    switch($cl)
    {
     case 0:
        $cla = 'Universal';
        break;
     case 1:
        $cla = 'application';
        break;
     case 2:
        $cla = 'context-specific';
        break;
     case 3:
        $cla = 'private';
        break;
    }
    //Dump some info
    printf("[$cla] Type: %x (%d), len: %d\r\n",$type,$type,$len);
    //Read data chunk
    $data = fread($f,$len);
    //Display data chunk based on type
    switch($type)
    {
     case 2: // integer
        break;
     case 3: // bit string
        break;
     case 4: // octet string
        break;
     case 5: // null
        break;
     case 6: // object identifier
        break;
     case 16: // sequence and sequence of
        break;
     case 17: // set and set of
        break;
     case 19: //string
        printf("Data: $data\r\n");
        break;
     case 20: // t61string
        break;
     case 22: // ia5string
        break;
     case 23: // utctime
        break;
     default:
        #printf("Data: $data\r\n");
        break;
    }
    //increment count
    $c++;
    //check if we reach the number of tag specified
    if (($c>$limit)&&($limit>0)) break;
}
 
//close our input file
fclose($f);

Rest

Vendredi, décembre 14th, 2007

I’m used to be asked “what is REST?”, the answer is simple: “Rest is a development method that involve using HTTP methods to communicate to a web service.”

But when we got into details, digging the web, we found that some details are fuzzy.

The basics, using HTTP verbs GET, POST, PUT and DELETE is agreed by almost averyone. But what does each web is not well defined.

I recently read an article giving an interesting point of view.
GET is used to retrieve information.
POST is used to create or update a document by sending the data to an intermediate URL.
PUT is used to create or completly update a document name by it’s own URL.
DELETE is used to delete a document.

I should agree the detail that POST create a document by sending data to another URL seem right for me. We usally use POST on an URL representing the base of the final one. For example, we POST a “user” to something like http://server/users and that create a new document at an url like http://server/users/TheNewUser. And I also agree that PUT is used on a complete URL like http://server/users/TheUserID. But I disagree with the principle that PUT should always overwrite the document. Following the definition in the HTTP RFC the article is right! But for data consistency, if you allow an external call to define new document URL, you tend to broke the data consistency.

I think that you should only allow document creation by POSTing some data to the root url http://server/users and let the web service define the corresponding ID and URL as http://server/users/NewUserID and after that, allow updating the document using PUT method on it. I also recommand that PUTting or POSTing to the document URL only update part of the document that is sent (as partial form or some blocks) instead of overwriting the entire content. I recommand that to avoid need to first GET the entire document, merge the changes and PUT/POST it back to the server.

On top of that, I strongly recommand using HTTP authentification in the http://user:password@server/service form. You could access the user/pass within your software to extent access rights but your resources are web based protected. The output format should also be negociated using HEADER strings

xmlrpc client (2) - php

Mercredi, juin 22nd, 2005
#!/usr/local/php4/bin/php
 
include "xmlrpc-1.0.99.2/xmlrpc.inc";
 
//First attempt to use XML_RPC calls
//assert( $c=new xmlrpc_client("/", "sundev02.grafsoft.com", 8888) );
assert( $c=new xmlrpc_client("/~jlcyr/rpc_server.php", "192.168.2.21", 80) );
$c->setDebug(1);//never set it to 1 on an agi script..!!
 
////////////////////
// Envoie d'un fichier binaire
/*
$fn = "01.mp3";
$fich = fopen($fn,"rb");
$select = fread($fich,filesize($fn));
echo "filesize:".filesize($fn)."\n";
fclose($fich);
assert( $f=new xmlrpcmsg('doc.putDoc',array(new xmlrpcval($select,"base64"),new xmlrpcval($fn,"string"))) );
assert( $r=$c->send($f) );
$v=$r->value();
if ($r->faultCode())
  {
    //Insert error flag and message into db
    print "Fault: ";
    print "Code: " . $r->faultCode() . " Reason '" .$r->faultString()."'
";
  }
else
  {
    //Dump received return value
    print $v->scalarval();
  }
*/
 
//////////////////
// Demande des infos du RIS
//assert( $f=new xmlrpcmsg('ris.getCMD',array(new xmlrpcval("9999999","string"),new xmlrpcval("2","string"))) );
assert( $f=new xmlrpcmsg('doc.getDocInfo',array(new xmlrpcval("902","string"),
					    new xmlrpcval("fileset200525","string"),
					    new xmlrpcval("filename1.2.3","string"))));
assert( $r=$c->send($f) );
$v=$r->value();
if ($r->faultCode())
  {
    //Insert error flag and message into db
    print "Fault: ";
    print "Code: " . $r->faultCode() . " Reason '" .$r->faultString()."'
";
  }
else
  {
    //Dump received return value
    while (list($key,$item)=$v->structeach()) {
      print $key."=".$item->scalarval()."\n";
    }
  }
 
?>

Serveur XML RPC (2) - PHP

Mercredi, juin 22nd, 2005

<?php // Title: Example de serveur XML-RPC en php // Version: 0.2 // Author: Jean-Luc Cyr  // Desc: Replacement for python xml-rpc server that handle //       imagem phone dictation system and audio-context calls.  // Exemple avec l’extension disponible // http://phpxmlrpc.sourceforge.net/  include “xmlrpc-1.0.99.2/xmlrpc.inc”; include “xmlrpc-1.0.99.2/xmlrpcs.inc”;  // Declare global vars  //Setup parameters //Database user name $duser = “transcription”; //$duser = “DICTWEB”; //Database password //$dpass = “password”; $dpass = “imagemsoft”; //Database tnsname //$dhost = “interweb”; $dhost = “rcorcl”; //Document base path //$base_base = “/export/home/dictedoc/”; $base_path = “/export/home/jlcyr/tmp/”;  $db = oci_pconnect($duser,$dpass,$dhost);       // Declare rpc_server possible methods $s=new xmlrpc_server( array(”doc.putDoc” => array (”function” => “doc_putDoc”), 			    “doc.getDocInfo” => array (”function” => “doc_getDocInfo”), 			    “doc.createDoc” => array (”function” => “doc_createDoc”), 			    “doc.getUID” => array (”function” => “doc_getUID”), 			    “doc.updateDOC” => array (”function” => “doc_updateDoc”), 			    “doc.help” => array (”function” => “doc_help”), 			    “ris.getBirth” => array(”function” => “risCMD_getBirth”), 			    “ris.getCMD” => array(”function” => “risCMD_getCMD”), 			    “ris.help” => array(”function” => “risCMD_help”), 			    “sql.execSql” => array(”function” => “sql_execSql”), 			    “sql.getInst” => array (”function” => “sql_getInst”), 			    “sql.help” => array (”function” => “sql_help”) 			    ));  oci_close($db);  // Don’t know why, but seen we can’t pass class method to xmlrpc_server array of function // so i’ve declared stand alone functions  ///////////////////////////////////////////////////////////////////////////////////////// // doc_putDoc invoqué via le web sous doc.putDoc // args: 1-Le contenu du document urlencoded //       2-Le path du media file set a concatener avec le root (global $base_path) //       3-Le nom du fichier à créer // retour: 0 function doc_putDoc($params)//($doc, $path, $filename) {   global $base_path;    $doc=$params->getParam(0)->scalarval();   $path=$params->getParam(1)->scalarval();   $filename=$params->getParam(2)->scalarval();    //Est-ce que le répertoir /export/home/dictedoc/$path existe?   if (!file_exists($base_path.$path))     {       //Si non le créer et le mettre chmod 777       mkdir($base_path.”/”.$path,0777,true);       chmod($base_path.”/”.$path,0777);     }    //Enregistrer le document $doc sous /export/home/dictedoc/$path/$filename   $f = fopen($base_path.”/”.$path.”/”.$filename,”w”);   $data = urldecode($doc);   fwrite($f,$data);   fclose($f);   chmod($base_path.”/”.$path.”/”.$filename,0777);    return new xmlrpcresp(new xmlrpcval(0,”integer”)); }  ///////////////////////////////////////////////////////////////////////////////////////// // doc_getDocInfo invoqué via le web sous doc.getDocInfo // args: le dd_id // retour: toutes les colonnes function doc_getDocInfo($params)//($info) {   global $db;   if ($db==false)       return new xmlrpcresp(new xmlrpcval(”Error connection to db “,”string”));    $info =$params->getParam(0)->scalarval();   $select = “select * from dictation_document where dd_id=’$info’”;   $arr = array();   //Execute select, return result values 1,2,3 in uid, id, fileset   $stmt = oci_parse($db,$select);   if (oci_execute($stmt,OCI_DEFAULT))     {       if (oci_fetch($stmt)) 	{ 	  $ncols = OCINumCols($stmt); 	  for ($i = 1; $i <= $ncols; $i++) { 	    $column_name  = OCIColumnName($stmt, $i); 	    $column_type  = OCIColumnType($stmt, $i); 	    $column_size  = OCIColumnSize($stmt, $i); 	    $column_data = OCIResult($stmt, $i);     	    $arr = $arr + array($column_name => new xmlrpcval($column_data,”string”)); 	  } 	}       else 	{ 	  return new xmlrpcresp(new xmlrpcval(”Error fetching result “,”string”)); 	}     }   else     {       return new xmlrpcresp(new xmlrpcval(”Error executing select “.$select,”string”));     }    return new xmlrpcresp(new xmlrpcval($arr, “struct”)); }  ///////////////////////////////////////////////////////////////////////////////////////// // args: le select à exécuter // retour: string “Doc Created” function doc_createDoc($params)//($select) {   $select = $params->getParam(0)->scalarval();    global $db;   if ($db==false)       return new xmlrpcresp(new xmlrpcval(”Error connection to db “,”string”));    //Execute select, return result values 1,2,3 in uid, id, fileset   $stmt = oci_parse($db,$select);   if (oci_execute($stmt,OCI_DEFAULT))     {       oci_commit($db);     }    //Executer le select dans $select    return new xmlrpcresp(new xmlrpcval(”Doc Created”,”string”)); }  ///////////////////////////////////////////////////////////////////////////////////////// // args: un service id // retour: struct: uid, id et fileset pour créer un nouveau document function doc_getUID($params)//($seruid) {   global $db;   if ($db==false)       return new xmlrpcresp(new xmlrpcval(”Error connection to db “,”string”));    $seruid = $params->getParam(0)->scalarval();    $select = “select ‘2.16.124.10.2.1.3.100.’ “.     “||to_char(sysdate,’YYYYMMDD’)||’.'”.     “||to_char(to_number(to_char(to_date(’010203′,’HH24MISS’),’HH24MISS’)))||’.'”.     “||(select CE_VALUE from config_env where CE_ITEM_CONF=’INSTITUTION’)||’.'”.     “||SQ_DICTATION_UID.NEXTVAL,”.     “to_char(SQ_DICTATION_UID.NEXTVAL), “.     “(select DS_NAME from DICTATION_SERVICE where DS_ID=’$seruid’)||’/'||to_char(sysdate,’YYYYIW’) from dual”;    //Execute select, return result values 1,2,3 in uid, id, fileset   $stmt = oci_parse($db,$select);   if (oci_execute($stmt,OCI_DEFAULT))     {       if (oci_fetch($stmt)) 	{ 	  $uid = oci_result($stmt,1); 	  $id = oci_result($stmt,2); 	  $fileset = oci_result($stmt,3); 	  //oci_commit($this->link); 	}       else 	{ 	  return new xmlrpcresp(new xmlrpcval(”Error fetching result “,”string”)); 	}     }   else     {       return new xmlrpcresp(new xmlrpcval(”Error executing select “.$select,”string”));     }    $arr = array( “uid” => new xmlrpcval($uid,”string”), 		“id” => new xmlrpcval($id,”string”), 		“fileset” => new xmlrpcval($fileset,”string”) );    return new xmlrpcresp(new xmlrpcval($arr, “struct”)); }  ///////////////////////////////////////////////////////////////////////////////////////// // Not done function doc_updateDoc() {   return new xmlrpcresp(new xmlrpcval(”Doc Updated”,”string”)); }  ///////////////////////////////////////////////////////////////////////////////////////// // doc_help invoqué via le web sous doc.help // args: aucun // retour: 1-liste des méthodes de l’objet web doc function doc_help() {   return new xmlrpcresp(new xmlrpcval(”putDoc, getDocInfo, createDoc, getUID, updateDoc”, “string”)); }  ///////////////////////////////////////////////////////////////////////////////////////// // args: un patient id // retour: la date de naissance sous forme de string ou 0 si le patient n’existe pas function risCMD_getBirth($params)//($patid) {   $patid =$params->getParam(0)->scalarval();    $select = “select * from WEB.PATIENT where PAT_ID=’$patid’”;    global $db;   if ($db==false)       return new xmlrpcresp(new xmlrpcval(”Error connection to db “,”string”));    $stmt = oci_parse($db,$select);   if (oci_execute($stmt,OCI_DEFAULT))     {       if (oci_fetch($stmt)) 	{ 	  $birth = oci_result($stmt,”PAT_BIRTH”); 	}       else 	{ 	  return new xmlrpcresp(new xmlrpcval(0, “integer”)); 	  //return new xmlrpcresp(new xmlrpcval(”Error fetching result “,”string”)); 	}     }   else     {       return new xmlrpcresp(new xmlrpcval(0, “integer”));       //return new xmlrpcresp(new xmlrpcval(”Error executing select “.$select,”string”));     }    return new xmlrpcresp(new xmlrpcval($birth, “string”)); }  ///////////////////////////////////////////////////////////////////////////////////////// // args: le staff id et le délai maximum de validité du click dans le ris // retour: toutes les colonnes de la table RIS_DICTATION_INTERFACE function risCMD_getCMD($params)//($staffid, $gap) {   global $db;   if ($db==false)       return new xmlrpcresp(new xmlrpcval(”Error connection to db “,”string”));    $staffid = $params->getParam(0)->scalarval();   $gap = $params->getParam(1)->scalarval();    $select = “select * from RIS_DICTATION_INTERFACE where RDI_STAFF_ID=’$staffid’ and RDI_DT>(sysdate-$gap/(24*60)) order by RDI_DT desc”;    //Execute select, Return all values in the array   $arr = array();   $stmt = oci_parse($db,$select);   if (oci_execute($stmt,OCI_DEFAULT))     {       if (oci_fetch($stmt)) 	{ 	  $ncols = OCINumCols($stmt); 	  for ($i = 1; $i <= $ncols; $i++) { 	    $column_name  = OCIColumnName($stmt, $i); 	    $column_type  = OCIColumnType($stmt, $i); 	    $column_size  = OCIColumnSize($stmt, $i); 	    $column_data = OCIResult($stmt, $i);     	    $arr = $arr + array($column_name => new xmlrpcval($column_data,”string”)); 	  } 	}       else 	{ 	  return new xmlrpcresp(new xmlrpcval(0, “integer”)); 	  //return new xmlrpcresp(new xmlrpcval(”Error fetching result “,”string”)); 	}     }   else     {       return new xmlrpcresp(new xmlrpcval(0, “integer”));       //return new xmlrpcresp(new xmlrpcval(”Error executing select “.$select,”string”));     }    return new xmlrpcresp(new xmlrpcval($arr, “struct”)); }  ///////////////////////////////////////////////////////////////////////////////////////// function risCMD_help() {   return new xmlrpcresp(new xmlrpcval(”getBirth, getCMD”, “string”)); }  ///////////////////////////////////////////////////////////////////////////////////////// // args: l’affirmation sql a exécuter // retour: la string “Sql Done” function sql_execSql($param)//($select) {   global $db;   if ($db==false)       return new xmlrpcresp(new xmlrpcval(”Error connection to db “,”string”));    $select = $params->getParam(0)->scalarval();    //Execute select, with commit   $stmt = oci_parse($db,$select);   if (oci_execute($stmt,OCI_DEFAULT))     {       oci_commit($db);     }    return new xmlrpcresp(new xmlrpcval(”Sql Done”, “string”)); }  ///////////////////////////////////////////////////////////////////////////////////////// // args: N/A // retour: le numéro d’institution défini dans la table config_env sous institution //         ou 0 si non défini. function sql_getInst() {   global $db;   if ($db==false)       return new xmlrpcresp(new xmlrpcval(”Error connection to db “,”string”));    $select = “select CE_VALUE from config_env where CE_ITEM_CONF=’INSTITUTION’”;    //Execute select, return result value in $inst as a string   $stmt = oci_parse($db,$select);   if (oci_execute($stmt,OCI_DEFAULT))     {       if (oci_fetch($stmt)) 	{ 	  $inst = oci_result($stmt,”CE_VALUE”); 	}       else 	{ 	  return new xmlrpcresp(new xmlrpcval(0, “integer”)); 	  //return new xmlrpcresp(new xmlrpcval(”Error fetching result “,”string”)); 	}     }   else     {       return new xmlrpcresp(new xmlrpcval(0, “integer”));       //return new xmlrpcresp(new xmlrpcval(”Error executing select “.$select,”string”));     }    return new xmlrpcresp(new xmlrpcval($inst, “string”)); }  ///////////////////////////////////////////////////////////////////////////////////////// function sql_help() {   return new xmlrpcresp(new xmlrpcval(”execSql, getInst”, “string”)); }  //Exemple de retour de message d’erreur //return new xmlrpcresp(0, $xmlrpcerruser+3, “Select return an error”); //return new xmlrpcresp($retVal);//OK