Nov 30, 2008

Even PHP sometimes needs explicit data type conversions

If you're new to PHP, everything seems so easy... When printing, integers automaticly become strings, when parsing user input, strings are automaticly numbers... But sometimes that system fails. You always need to be sure what you're gonna get or use.

It happened to me one day, when writing my Briscola socket server - I was parsing an XML and expecting a number in a node, so I could use it to access a certain index in the array. Of course the array index was numeric, and I had to do a
$my_number += 0;
to it. Which is kinda dumb, but it worked. It fixed the error, and everything went smooth. But that's not really the way to do it,
$my_number = intval($my_number);
is.

Nov 23, 2008

Writing a chat server socket in PHP

UPDATE: Check out this article for more information

I've spent quite a few hours around this to learn a few tips and tricks:
  • Don't use PHP's socket_read() - allthough with PHP_BINARY_READ you *CAN* solve a lot of your problems, but not all of them. I noticed that eventually the client socket "jamms" because the buffer doesn't clear, so you get stuck with a socket that you can only write to, but when you try to read from this socket, nothing returns. A very good alternative is socket_recv()
  • OOP (Object Oriented Programming) is a good thing, it makes upgrades and fixes easy to do, so at least you would need two classes, one for the server and one for a user. Each user is an object.
  • When reading from a socket, concatenated commands may occur, use a special delimiter (char(0) works) to split them.
  • Use nonblocking sockets, you don't want your server to freeze everytime a client socket writes.
  • "Ping" your clients, sometimes the kill signal gets lost, the server thinks the socket is still active and unitl you write to that socket, there is no way of knowing if the connection is still established or not. Disconnect the socket on read or write error and that way your sockets will be purged automatically.
Here's a rough framework of what I'm talking about (may be updated some time soon):
class user {
 var $socket;
 function user($socket) {
  $this->socket=$socket;
 }
}

class server {
 var $socket;
 var $working;
 var $clients;
 
 //constructor
 function server($port) {
  $this->socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
  socket_set_option($this->socket,SOL_SOCKET,SO_REUSEADDR,1);
  socket_bind($this->socket,0,$port);
  socket_listen($this->socket);
  socket_set_nonblock($this->socket);
  $this->working = true; //if all else fails, this does too!
  array_push($this->clients($this->socket));
 }
 
 function me($sock) {
  //if the socket is the server socket
  return $this->socket == $sock;
 }
 
 //read from the buffer
 function read(&$sock,$i,$len=2048,$flag=0) {
 
 $recv_data = @socket_recv($sock,$jammeddata,$len,$flag);
 if ($recv_data == 0) {    
  //error on read or client quitted
  $this->remove_client($sock);
 } else {
  //reading from socket
  $jammed = explode(chr(0), $jammeddata); //is it jammed?
  if (count($jammed) > 2) {
   //socket is jammed, parse it
   foreach($jammed as $unjammed) {
    $this->on_read($unjammed,$i);
   }
   return true;
  }
  //clean read
  return $this->on_read($jammeddata,$i);
 }

 return false;
}
 
 //event handler - PUT ALL YOUR FUNCTIONS HERE
 function on_read() {
  
 }
}

$server = new $server(10000);

while($server->working) {
 
 //put all current clients in the array
 $clients = $server->clients;
 //put all sockets that are trying to wrote in the array
 socket_select($clients,$write=NULL,$except=NULL,0);
 
 //loop through the generated array of clients
 foreach($clients as $client) {
  if($server->me($client)) {
   //accept incoming connections
   array_push(new user(socket_accept($client)));
  }
  //read from the socket that is trying to write
  $server->read($client);
 }
 
}

UPDATE: Check out this article for more information

Oct 30, 2008

ActionScript: Passing parameters to onRelease and other event functions

As it turns out, you can't use parameters directly when defining an event function, for example:
myMovie.onRelease = function(param1,param2,param3) {
   //my code
}
The example above will generate a compiler error. This won't work either:
var = 1;
var2 = "something else";
myMovie.onRelease = function() {
   //var and var1 are unaccessible at this point
}
The solution for this is simple, yet effective. You need to define your paramaters to a movieclip, so that you can reach them with the operator "this".
myMovie.param1 = "something";
mymovie.param2 = "something else";
myMovie.onRelease = function() {
   trace(this.param1);
   trace(this.param2);
}

Oct 4, 2008

PHP: function to see if an email is valid

function email_valid($email) {
 return (eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $email));
}
Return values are true/false.

Oct 2, 2008

jQuery - update DIV's HTML dynamically

jQuery is a JavaScript library, downloadable here. It uses AJAX calls to get external data. Retrieving this data is simple - I used two functions:
function geturl(addr) {
var r = $.ajax({
 type: 'GET',
 url: addr,
 async: false
}).responseText;
return r;
}

function changediv() {
$('#div_id').html(geturl('http://www.example.com'));
}


UPDATE: For asynchronous ajax calls see example in the comments below.

Sep 27, 2008

MSN Plus : simple countdown script

Simplest countdown script for MSN Plus. Seriously.
//Countdown date
TehDatum = "October 13, 2008 22:40:00";
//Refresh timer in seconds
TehDelay = 1;
//the 'until' text
TehWha = "do 20 let !";
//What do display if the counter ended
TehAfter = "20 let !";
//Smallest unit: dan, ura, minuta, sekunda
TehMode = "sekunda";


//end config -----------------------------

function OnEvent_Initialize(MessengerStart){
 MsgPlus.AddTimer("RFR",1000);
}

function OnEvent_Signin(Email) { 
 MsgPlus.AddTimer("RFR",1000);
}

function OnEvent_Timer(sTimerId){
    if(sTimerId == "RFR"){
    
 var dns = new Date();
     var pb = new Date(TehDatum);
     var d = pb.getTime() - dns.getTime();
     
     d=d/1000;
     dni=Math.floor(d/3600/24);
     ur=Math.floor((d-(dni*3600*24))/3600);
     min=Math.floor((d-(dni*3600*24)-(ur*3600))/60);
     sec=Math.floor(d-(dni*3600*24)-(ur*3600)-(min*60));
     
time = "Še "+dni+" dni, "+ur+" ur, "+min+" minut in "+sec+" sekund "+TehWha;

if(TehMode == "dan") { 
time = "Še "+dni+" dni "+TehWha;
}   

if(TehMode == "ura") { 
time = "Še "+dni+" dni in "+ur+" ur "+TehWha;
}  

if(TehMode == "minuta") { 
time = "Še "+dni+" dni, "+ur+" ur in "+min+" minut "+TehWha;
}

   
    
         if(pb.getTime() < dns.getTime()) {
          time = TehAfter;
         }      

   Messenger.MyPersonalMessage = time;
         MsgPlus.AddTimer("RFR",TehDelay*1000);
    }
}

indexOf in PHP

I found this function very useful in almost every project I do. indexOf() returns element's key in an array.
The parameters for this function are:
- the array to search
- the value to search
Return value is the element key.
function indexof($array,$value) {
foreach($array as $key=>$val)
 if($val == $value) return $key;
}

Sep 24, 2008

ActionScript: Controling volume of all sounds

By creating a sound object with no target on the highest level, you can control volume of all sounds on the stage.
var s:Sound = new Sound();
s.setVolume(0);
This will mute all sounds. The setVolume() parameter is given as percentage, so the value is between 0 and 100 where 0 is muted.

Sep 20, 2008

PHP: redefining, deleting, adding functions on the fly

Allthough this is not possible with just pure PHP - quote from the manual "...nor is it possible to undefine or redefine previously-declared functions.". The only thing PHP CAN do is to create function anonymously with create_function(), which is a runkit equivalent to runkit_function_add(); Redefining and undefining is still possible with runkit functions. This requires an additional software install - it is a PHP addon (PECL extension), a brief howto is explained here: http://si2.php.net/manual/en/runkit.installation.php. If you're using FreeBSD, installation from ports is fairly simple, you just
cd /usr/ports/devel/pecl-runkit
make install clean
Afther that, the runkit functions run brilliantly and you can use tools like
runkit_function_add('testme','$a,$b','echo "The value of a is $a\n"; echo "The value of b is $b\n";');
runkit_function_redefine('testme','','echo "New Testme Implementation\n";');
runkit_function_copy('original','duplicate');
runkit_function_rename('duplicate','dupl1c4t3');
runkit_function_remove('original');
These are mostly examples from PHP.net, but you get the idea. There are not a lot of examples there, nor comments (which I find rather strange), so from this point on, you're on your own to explore further. I haven't used these functions yet, but I have an idea for when and where they could be useful - for example: My Online Briscola server runs on an endless PHP loop, so for any change I make, I need to restart the server, which is a bad option if there are users on the server. With runkit, I could put all updatable functions in a seperate include file and use runkit to refresh the include functions every few minutes. But remember, all paramaters in runkit are strings which can be quite confusing the first time you use it, but you'll get the hang of it.

PHP: XML Generator - array to xml converter

I created this class for my Online Briscola project - which is a client-server application, the client application is a flash movie and the server runs on PHP sockets. They comunicate through XML commands, so this class is basicly an array-to-xml converter. It uses PHP's XMLWriter
<?
class xmlgen {

 var $xml;
 var $ver;
 var $charset;
 
 function xmlgen($ver='1.0',$charset='UTF-8') {
  $this->ver = $ver;
  $this->charset = $charset;
 }

 function generate($root,$data=array()) {
  $this->xml = new XmlWriter();
  $this->xml->openMemory();
  $this->xml->startDocument($this->ver,$this->charset);
  $this->xml->startElement($root);
  $this->write($this->xml, $data);
  $this->xml->endElement();
  $this->xml->endDocument();
  $xml = $this->xml->outputMemory(true);
  $this->xml->flush();
  return $xml;
 }
 
 function write(XMLWriter $xml, $data){
     foreach($data as $key => $value){
         if(is_array($value)){
             $xml->startElement($key);
             $this->write($xml,$value);
             $xml->endElement();
             continue;
         }
         $xml->writeElement($key,$value);
     }
 }
 
}
?>
When the object is constructed
$xmlgen = new xmlgen();
you can pass your array to the class' generate() function, for example
$array = array(
 "first_element"=>"element_value",
 "second_element"=>array(
  "second_element_value1"=>"value1_subvalue")
);

echo $xmlgen->generate('root',$array);
The output will be something simmilar to:
<?xml version="1.0" encoding="UTF-8"?>
<root>
 <first_element>
   element_value
 </first_element>
 <second_element>
  <second_element_value1>
      value1_subvalue
  </second_element_value1>
 </second_element>
</root>

Sep 19, 2008

PHP: sudoku solver

This was also my assignment in college, allthough in Java, but I like it better in PHP. You can see this script live on http://www.kafol.net/sudoku.
<?php
set_time_limit(500);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1250" />
<title>Sudoku solver</title>
</head>

<body>
<h3>- jean caffou</h1>
<form id="form1" name="form1" method="post" action="">
  <label>
  <textarea name="grid" id="grid" cols="20" rows="12"><?
if(isset($_POST['grid'])) echo $_POST['grid']; else { ?>0 9 0  3 0 0  0 0 0
4 0 8  1 0 0  6 7 5
1 0 6  8 0 0  0 0 0

6 0 3  0 0 0  0 5 0
2 0 0  0 1 0  0 0 9
0 7 0  0 0 0  2 0 6

0 0 0  0 0 2  1 0 8
8 2 9  0 0 1  5 0 4
0 0 0  0 0 3  0 9 0<? } ?></textarea>
  </label>
  <label>  <br />
  Vnesi ?tevke od 1-9 v ?tevilsko mre?o. Kjer je mesto prazno, vnesi 0.<br />
  <input type="submit" name="button" id="button" value="Re?i" />
  </label>
</form>
<?php
  $grid=array(array());
 $solvable = false;
 //////////////////////////////////////////////////////////////////////
if(isset($_POST['grid'])) {
 
 $str=$_POST['grid'];
 $elements=split("[\n\r\t ]+",$str);
 //elements must containt 81 numeric values
 $x=0;
 $y=0;
 if(count($elements)!=81) { echo "<center><h1>Neveljavna matrika"; exit; }
 for($i=1;$i<=81;$i++) {
  $val=$elements[$i-1];
  $grid[$y][$x]=$val;
  if(!($val>=0&&$val<=9)) { echo "<center><h1>Neveljavna matrika"; exit; }
  $x++;
  if($x==9) {
   $x=0;
   $y++;
  }
  
 }
 $orig=$grid;
 if(solve(0,0)) disp();
 if(!$solvable) echo "<h1>Ni re?itev.";
}

 function solve($y,$x) {
  global $grid,$solvable;
  if($x==9) {
   $y++;
   $x=0;
   if($y==9) {
    $solvable=true;
    return true;
   }
  }
  
  if($grid[$y][$x]!=0) { //this position is already solved
   return solve($y,$x+1);
  }
   
  for($n=1;$n<=9;$n++) {
   if(ok($y,$x,$n)) {
    $grid[$y][$x]=$n;
    if(solve($y,$x+1)) {
     disp();
     $solvable=true;
    }
   }
  }
  
  $grid[$y][$x]=0;
  return false;
 }
 
 function ok($y,$x,$n) {
  global $grid;
  for($i=0;$i<9;$i++) { //row
   if($grid[$y][$i]==$n) return false;
   if($grid[$i][$x]==$n) return false;
  }
  $r=floor($y/3)*3;
  $c=floor($x/3)*3;
  for($a=$r;$a<$r+3;$a++)
   for($b=$c;$b<$c+3;$b++)
    if($grid[$a][$b]==$n) return false;
  
  return true;
 }
 
 function disp() {
  global $grid,$orig;
  echo "<p><table border=\"2\">";
  for($y=0;$y<9;$y++) {
   echo "<tr>";
   if(($y+1)%3==1&&$y>2) echo "<tr></tr>";
   for($x=0;$x<9;$x++) {
    $v=$grid[$y][$x];
    $s="";
    if($orig[$y][$x]!=$grid[$y][$x]) $s="<font color=red>";
    echo "<td><strong>$s $v </td>";
    if(($x+1)%3==0&&$x<8) echo "<td>  </td>";
   }
   echo "</tr>";
  }
  echo "</table></p><br>";
 }
?>
</body>
</html>

Java :: Working with matrixes

I had an assignment in college to build a Java program that would calculate matrix expressions. Examples for this were:
Expression: A = [ [ 1 2 ] [ 3 4 ] ]

saves matrix

1 2
3 4

to variable A.

Expression: B = A * A

calculates the matrix A*A and saves the result in variable B

Expression: B - [ [ 9 8 ] [ 7 6 ] ]

calculates matrix B - matrix

9 8
7 6

and prints the result
Here's the class:
import java.util.*;
import java.io.*;

public class Matrike {
 //v hashmap se bodo shranjevale spremenljivke in njihove vrednosti
 static Map<String,String> vars = new HashMap<String,String>();
 static boolean debug=false; //param debug za podrobnejsi izpis
 static boolean gotSyntaxError; //ne izpisi rezultata, ce je napaka
 
/****************************************************************************************
   M A I N (done)
****************************************************************************************/ 
 public static void main(String[] args) {
  String niz = null;
  boolean ok=false;
  if(args.length>0)debug=args[0].equals("debug"); //debug=true/false
  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  
  do {
   System.out.printf(": ");
   ok = false;
   try {
    niz = br.readLine();
    ok = true;
   }
   catch(IOException ioe) {
    System.out.printf("! Input error\n");
    ok = false;
   }
   if(ok && niz.length() > 0) {
    analiza(niz); //ce je vse ok in ni prazn string, zacni procesirat
   }
  } 
  while (!niz.equals("exit")); //exit = komanda za izhod
  System.out.println("* Bye");
 }
 
/****************************************************************************************
   P R O C E S I R A N J E       K O M A N D E (done)
****************************************************************************************/  
 //analiza inputa - shrani spremenljivke, poslje izraz v funkcijo za racunanje
 public static void analiza(String niz) { 
  StringBuffer varBuffer = new StringBuffer();
  StringBuffer valBuffer = new StringBuffer();
  
  String val=null; //desna stran enacaja
  String var=null; //spremenljivka
  
  gotSyntaxError=false;
/////////////////////////////////////////////////////////////////////////////////////////  
  //[komande] izpisi vse spremenljivke
  if(niz.equals("vars")||niz.equals("var")||niz.equals("variables")){
   printVars();
   return;
  }
  if(niz.equals("clean")||niz.equals("clear")){
   vars.clear();
   System.out.println("* Cleaning up variables");
   return;
  }
///////////////////////////////////////////////////////////////////////////////////////// 
  //iskanje negativnih stevil, da se ne bo mesalo z operatorjem minus
  boolean foundOklepaj=false;
  StringBuffer nizReplace = new StringBuffer();
  for(int i=0;i<niz.length();i++) {
   if(niz.charAt(i)=='[')foundOklepaj=true; //ce je negativna cifra znotraj matrike
   if(niz.charAt(i)==']')foundOklepaj=false;
   if((niz.charAt(i)=='-')&&foundOklepaj) {
    nizReplace.append('_'); //bo znak za minus zamenjalo s _
   } else {
    nizReplace.append(niz.charAt(i));
   }
  }
  niz=nizReplace.toString(); 
///////////////////////////////////////////////////////////////////////////////////////// 
  //shrani izraz za racunanje, ce je najden enacaj je ta za enacajem
  int eqLoc=0;
  for(int i=0;i<niz.length();i++)if(niz.charAt(i)=='=')eqLoc=i+1; //+1, enacaja ne shrani
  for(int i=eqLoc;i<niz.length();i++)valBuffer.append(niz.charAt(i));
  val=valBuffer.toString();
/////////////////////////////////////////////////////////////////////////////////////////  
  //ce so v izrazu operatorji, je treba izraz poracunat in popravit spremenjivko val
  int nOperations=0;
  for(int i=0;i<niz.length();i++)
   if(niz.charAt(i)=='+'||niz.charAt(i)=='*'||niz.charAt(i)=='-') 
    nOperations++;
    
  if(nOperations>0) { //ali je treba racunat?
   ///////POSLJI V KALKULATOR
   val = calcMatrix(val,nOperations); //treba je racunat, calcMatrix bo vrnila nov rezultat
   ///////----------
   if((val != null) && (!gotSyntaxError)) { //izpise pa ga tule, ne calcMatrix, pa izpisi ce ni kasn error
    if(isScalar(val)) { //ce je matrika enodimenzionalna, je skalar - pretvori
     StringBuffer toScalar = new StringBuffer();
     for(int i=0;i<val.length();i++)
      if( (val.charAt(i)!=' ') && (val.charAt(i)!='[') && (val.charAt(i)!=']') )
       toScalar.append(val.charAt(i));
     val=toScalar.toString();
    }
    //TUKAJ JE GLAVNI IZPIS REZULTATA !!!
    System.out.printf("> %s\n",val);
    //----
   }
  }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //shrani spremenljivke
  for(int i=0;i<niz.length();i++) {
   if(niz.charAt(i)=='=') {
    for(int j=0;j<i;j++)varBuffer.append(niz.charAt(j));
    var=varBuffer.toString();
    vars.put(var.replaceAll(" ",""),val);
   }
  } 
 }
 
/****************************************************************************************
   R A C U N A N J E   I Z R A Z A   M A T R I K (done)
****************************************************************************************/ 
 public static String calcMatrix(String matrix,int nOperations) {
 /*
  kalkulator deluje na isti princip kot racuni.c - naredi dve tabeli:
   - tabela operandov
   - tabela operatorjev
   Nato se sprehajamo po tabeli operatorjev po prioriteti in racunamo po dva elementa hkrati.
   Rezultat napisemo v indeks prvega elementa, drugi element zbrisemo in zmanjsamo tabelo za 1 in
   pomaknemo v levo.
   Tabela je tridimenzionalna - prvi indeks je indeks operandov, druga dva indeksa sta 2D tabela matrike
  */
  int[][][] izraz = new int[nOperations+1][][];
  char[] operatorji = new char[nOperations];
  String result=null;
  int a=0;
  
  //shrani operatorje
  for(int i=0;i<matrix.length();i++)
   if(matrix.charAt(i)=='+'||matrix.charAt(i)=='*'||matrix.charAt(i)=='-') {
    operatorji[a]=matrix.charAt(i);
    a++;
   }  
  
  //shrani operande (matrike) v tabelo
  a=0;
  String tmp=null;

  //StringTokenizer st = new StringTokenizer(matrix,"+-*"); //razbij po operatorjih
  String tokens[] = matrix.split("\\+|\\-|\\*");
  //while (st.hasMoreTokens()) {
  for(int i=0;i<tokens.length;i++) {
   //tmp=st.nextToken();
   tmp=tokens[i];
   
   //poglej ce je tmp spremenljivka in jo zamenjaj z matriko
   tmp=varToMatrix(tmp);
   
   //poglej ce je tmp skalar in ga zamenjaj v 1x1 matriko ;-)
   if(isNumber(tmp)) {
    tmp=tmp.replaceAll(" ","");
    StringBuffer skalar = new StringBuffer();
    skalar.append("[[");
    try {
     skalar.append(Integer.parseInt(tmp));
    }
    catch(NumberFormatException e) {
     System.out.printf("! Syntax error: scalar is not a number\n");
     gotSyntaxError=true;
     return null;
    }
    skalar.append("]]");
    tmp=skalar.toString();
   }
   
   /*Y**************************************************************************************/
   //poracunaj dimenzije tabele
   int y=getMatrixDimensionY(tmp);
   /*X*************************************************************************************/
   int x=getMatrixDimensionX(tmp);
   /***************************************************************************************/
   int counter=0; //to je sam za cekiranje

   try {
    //StringTokenizer stCount = new StringTokenizer(tmp," ][");
    String numberTokens[]=tmp.split(" |\\[|\\]");
    //while(stCount.hasMoreTokens()){
    for(int w=0;w<numberTokens.length;w++) {
     if((numberTokens[w]!=null) && (!numberTokens[w].equals(""))) counter++;
     //stCount.nextToken();
    }
   }
   catch(NullPointerException e) {
    System.out.println("! Syntax error: empty variable, clean up with 'vars'");
    gotSyntaxError=true;
    return null;
   }

   if(debug)System.out.printf("calcMatrix? x=%d,y=%d\n",x,y);
   /***************************************************************************************/
   
   //ce je x ali y negativen, ali nista kolicnika je struktura matrike nepravilna
   if(x==0||y==0) {
    System.out.printf("! Syntax error: no numbers in the matrix\n");
    gotSyntaxError=true;
    return null;   
   }
   if(x<0||y<0||counter%y!=0){
    System.out.printf("! Syntax error: invalid matrix dimension\n");
    gotSyntaxError=true;
    return null;
   }
   if((x>1)&&(counter%x!=0)) {
    System.out.printf("! Syntax error: missing number in the matrix\n");
    gotSyntaxError=true;
    return null;
   }
   
   //pretvori string v tabelo integerjev    
   izraz[a] = new int[x][y];
   izraz[a]=matrixToTable(tmp,x,y);
   a++;
  } 

  ////////////////////////////////////////////////////////////////////////////////////////////////////
  //TABELA JE SHRANJENA, zacni racunat
  int lenOperatorji=operatorji.length;
  int lenIzraz=izraz.length;
  
  String rezultat=null;
  /***** ISCI OPERATORJE IN POPRAVLJAJ TABELO ! *****/
  for(int op=1;op<4;op++) {
   char f;
   switch(op) {
   default:
    case 1:f='*'; break;
    case 2:f='-'; break;
    case 3:f='+'; break;
   }
   int stejop=0;
   for(int i=0;i<lenOperatorji;i++) 
    if(operatorji[i]==f)stejop++;
   while(stejop>0) {
    for(int i=0;i<lenOperatorji;i++) { //break =>
     if(operatorji[i]==f) {
      if((isScalar(tableToMatrix(izraz[i])) || isScalar(tableToMatrix(izraz[i+1]))) && (f=='*')) { //ali je operacija s skalarjem
       //pozor: ta funkcija je definirana samo za mnozenje s skalarjem (ali ce sta oba skalarja), v drugem primeru se bo obravnavalo kot operacijo med dvema matrikama
       rezultat=doMatrixMath(izraz[i],izraz[i+1],'s');
       int x=getMatrixDimensionX(rezultat);
       int y=getMatrixDimensionY(rezultat);
       if(x>0||y>0)
        izraz[i]=matrixToTable(rezultat,x,y); 
       if(debug)System.out.printf("calcMatrix/ (Scalar) Set %s\n",rezultat);     
      } else { //drugace...
       rezultat=doMatrixMath(izraz[i],izraz[i+1],f);
       if(debug)System.out.printf("calcMatrix/ Got %c\n",f);
       int x=getMatrixDimensionX(rezultat);
       int y=getMatrixDimensionY(rezultat);
       if(x>0||y>0)
        izraz[i]=matrixToTable(rezultat,x,y); 
       if(debug)System.out.printf("calcMatrix/ Set %s\n",rezultat);
      }
      ////////////Popravi tabelo
      for(int j=i;j<lenOperatorji;j++)
       if(j+1<lenOperatorji)operatorji[j]=operatorji[j+1]; //kle!
      lenOperatorji--;
      //se operande
      for(int j=i+1;j<lenIzraz;j++) 
       if(j+1<lenIzraz)izraz[j]=izraz[j+1];
      lenIzraz--;
      ////////ok
      stejop--;
      break; // <= break
     }
    }
   }
  }
  
  result=tableToMatrix(izraz[0]);
  if(debug)System.out.printf("calcMatrix$ %s\n",result);
  return result;
 }

/****************************************************************************************
   METODA ZA DIMENZIJE MATRIKE ZA 2D TABELO (done)
****************************************************************************************/  
 public static int getMatrixDimensionX(String matrix) {
  int f=-1,g=-1,x=-1;
  if(matrix!=null) {
   for(int i=0;i<matrix.length();i++)if(matrix.charAt(i)=='[')f++;
   //x dimenzija tabele = N("[")-1
   for(int i=0;i<matrix.length();i++)if(matrix.charAt(i)==']')g++;
   if(g==f)x=g;
  }
  return x;
 }
 public static int getMatrixDimensionY(String matrix) {
  int y=-1;
  int counter=0;
  if(matrix==null||matrix.equals("")||matrix.equals(null)) {
   if(debug)System.out.println("! Syntax error: null parameter (getMatrixDimension)");
   gotSyntaxError=true;
   return -1;
  }
  String tmp=matrix;
  if(tmp==null||tmp.equals("")||tmp.equals(null)) {
   if(debug)System.out.println("! Syntax error: null parameter (getMatrixDimensionY)");
   gotSyntaxError=true;
   return -1;
  }
  if(debug)System.out.printf("getMatrixDimensionY# %s\n",tmp);
  if(tmp!=null) {
   if(debug)System.out.printf("getMatrixDimensionY# Tokenizing ...\n");
   //StringTokenizer stCount = new StringTokenizer(tmp," ][");
   String numberTokens[]=tmp.split(" |\\[|\\]");
   //while(stCount.hasMoreTokens()){
   for(int w=0;w<numberTokens.length;w++) {
    if((numberTokens[w]!=null) && (!numberTokens[w].equals(""))) counter++;
    //stCount.nextToken();
   }
  }
  y=counter/getMatrixDimensionX(tmp); 
  //y dimenzija tabele = N(stevilk)/x
  return y;
 }
 
/****************************************************************************************
   METODA ZA RACUNANJE DVEH MATRIK
****************************************************************************************/    
 public static String doMatrixMath(int[][] p1,int[][] p2,char f) {
  String result=null;

  if(p1==null||p2==null) {
   System.out.println("! Syntax error: parameter missing, nothing to do");
   gotSyntaxError=true;
   return null;
  }
  
  int x1=p1.length;
  int x2=p2.length;
  int y1=p1[0].length;
  int y2=p2[0].length;
  
  switch(f) {
   
   // MNOZENJE S SKALARJEM
   case 's':
    int scalar=0;
    result=tableToMatrix(p1);
    if(isScalar(tableToMatrix(p1))) {
     scalar=p1[0][0]; //doloci skalar
     for(int i=0;i<p2.length;i++) 
      for(int j=0;j<p2[i].length;j++)
       p2[i][j]*=scalar; //in pomnozi s drugim parametrom
     result=tableToMatrix(p2);
    } else { //ravno obratno
     scalar=p2[0][0];
     for(int i=0;i<p1.length;i++) 
      for(int j=0;j<p1[i].length;j++)
       p1[i][j]*=scalar;     
     result=tableToMatrix(p1);
    }
    break;
  
   // PLUS in MINUS  
   case '+':
   case '-':
    //vsota in razlika matrik je definirana samo za matrike enakih dimenzij
    //vir: http://en.wikipedia.org/wiki/Matrix_%28mathematics%29#Sum
    if(x1!=x2||y1!=y2) {
     System.out.println("! Syntax error: matrices do not have the same dimension");
     gotSyntaxError=true;
     return null;
    }
    for(int x=0;x<x1;x++) {
     for(int y=0;y<y1;y++) {
      switch(f) {
       default:
       case '+': p1[x][y]+=p2[x][y]; break;
       case '-': p1[x][y]-=p2[x][y]; break;
      }
     }
    }
    result=tableToMatrix(p1); 
    break;

   //KRAT    
   case '*':
   default:
    //mnozenje matrik je definirano za matrike, katere stevilo stolpcev ene matrike je enako stevilu vrstic druge
    //vir: http://en.wikipedia.org/wiki/Matrix_multiplication#Ordinary_matrix_product    
    int dx=0; //x dimenzija matrike produkta
    int dy=0; //y dimenzija matrike produkta
    int max=0; //sirsa dimenzija
    if(x1>=x2) { //p1 je daljsi v stolpcih ali pa sta p1 in p2 kvadrat
     dx=x2;
     dy=y1;
     max=x1;
    } else { //p2 je daljsi v stolpcih
     dx=x1;
     dy=y2;
     max=x2;
    }
    if(debug)System.out.printf("doMatrixMath: %d %d %d %d\n",x1,y2,x2,y1);
    if((x1!=x2||y1!=y2)&&(x1!=y2||x2!=y1)) {
     System.out.println("! Syntax error: matrices do not have the opposite or same dimension");
     gotSyntaxError=true;
     return null;
    }
    if(debug)System.out.printf("doMatrixMath-Multiplication:\ndx = %d\ndy = %d\nmax = %d\n",dx,dy,max);
    
    int[][] p = new int[dx][dy]; //dimenzije matrike produkta
    
    for(int xp=0;xp<dx;xp++) {
     for(int yp=0;yp<dy;yp++) {
      p[xp][yp]=0;
      for(int x=0;x<max;x++) {
       if(debug)System.out.printf("p[%d][%d] += p1[%d][%d](%d) * p2[%d][%d](%d)\n",
         xp,yp,xp,x,p1[xp][x],x,yp,p2[x][yp]);
       if(x1>=x2) p[xp][yp]+=p2[xp][x]*p1[x][yp];
       else p[xp][yp]+=p1[xp][x]*p2[x][yp];
      }
     }
    }
    result=tableToMatrix(p);
    break;
  }
  
  return result;
 }
 
/****************************************************************************************
   PRETVORBA MATRIKE IZ STRING V 2D TABELO INTEGER (done)
****************************************************************************************/   
 public static int[][] matrixToTable(String matrix,int x,int y) {
  int[][] result = new int[x][y];
  int[] nums = new int[x*y];
  
  //shrani stevilke v 1D tabelo
  int counter=0;
  //StringTokenizer st = new StringTokenizer(matrix," ][");
  String tokens[]=matrix.split(" |\\[|\\]");
  //while (st.hasMoreTokens()) {
  for(int w=0;w<tokens.length;w++) {
   try {
    //String tmp=st.nextToken();
    ////////
    String tmp = tokens[w];
    if((tokens[w]==null) || (tokens[w].equals(""))) continue;
    ///////
    tmp=tmp.replaceAll("_","-");
    try {
     nums[counter]=Integer.parseInt(tmp); 
    }
    catch(ArrayIndexOutOfBoundsException e) {
     System.out.printf("! Syntax error: unknown matrix array error\n");
     gotSyntaxError=true;
     return null;
    }
    if(debug)System.out.printf("matrixToTable+ %d\n",nums[counter]);
    counter++;
   }
   catch(NumberFormatException nfe) {  
    System.out.printf("! Syntax error: element in matrix is not a number\n");
    gotSyntaxError=true;
    //not a number
    return null;
   }
  }
  
  //zapis v 2D tabelo
  counter=0;
  for(int i=0;i<x;i++) {
   for(int j=0;j<y;j++) {
    result[i][j]=nums[counter];
    if(debug)System.out.printf("matrixToTable- {%d,%d} %d\n",i,j,nums[counter]);
    counter++;
   }
  }
  
  //vrni rezultat
  if(debug)System.out.printf("matrixToTable@ %s\n",tableToMatrix(result));
  return result;
 }

/****************************************************************************************
   PRETVORBA 2D TABELE V STRING MATRIKE ([[1 2][3 4]]) (done)
****************************************************************************************/  
 public static String tableToMatrix(int[][] tab) {
  StringBuffer matrix = new StringBuffer();
  String result=null;
  
  if(tab==null) {
   if(debug)System.out.println("! Syntax error: null parameter (tableToMatrix)");
   gotSyntaxError=true;
   return null;
  }
  
  matrix.append("[ ");
  for(int x=0;x<tab.length;x++) {
   matrix.append("[ ");
   for(int y=0;y<tab[x].length;y++) {
    matrix.append(tab[x][y]+" ");
   }
   matrix.append("] ");
  }
  matrix.append("]");
  
  //Lep izpis, primer:  [ [ 2 3 ] [ 4 5 ] ]
  result=matrix.toString();
  if(debug)System.out.printf("tableToMatrix: %s\n",result);
  return result;
 }
 
/****************************************************************************************
   IZPIS SPREMENLJIVK(done)
****************************************************************************************/   
 public static void printVars() {
  Set set = vars.entrySet();
  List<String> clean = new ArrayList<String>();
  Iterator i = set.iterator();
  String var,val;
  System.out.println("* Listing variables");
  while(i.hasNext()) { //sprehodi se po mapSetu
   Map.Entry entry = (Map.Entry) i.next();
   var = (String) entry.getKey();
   val = (String) entry.getValue();
   try {
    val = val.replaceAll("_","-"); //zajebi cel svet in izpisi pravilne minuse
    System.out.printf("# %s = %s\n",var,val);
   }
   catch(NullPointerException e) {
    System.out.printf("! Empty variable '%s' removed\n",var);
    clean.add(var); /* shrani seznam spremenljivk za izbris */
   }
  }
  /* pocisti prazne sprmenljivke */
  Iterator j=clean.iterator();
  while(j.hasNext())vars.remove(j.next());
  /* konec */
  System.out.println("* End of list");
 }

/****************************************************************************************
   VRACANJE VREDNOSTI SPREMENLJIVKE (done)
****************************************************************************************/   
 public static String varToMatrix(String tmp) {
  String result = tmp; //ce spremenljivka ne obstaja, vrni isti string
  
  StringBuffer buffer = new StringBuffer();
  for(int i=0;i<tmp.length();i++)
   if(tmp.charAt(i)!=' ')
    buffer.append(tmp.charAt(i));
  String chkEq = buffer.toString(); //v chkEq se nahaja spremenljivka
  if(debug)System.out.printf("varToMatrix# chkEq(%s)\n",chkEq);
  
  Set set = vars.entrySet();
  Iterator i = set.iterator();
  String var,val;
  while(i.hasNext()) {
   Map.Entry entry = (Map.Entry) i.next();
   var = (String) entry.getKey();
   val = (String) entry.getValue();
   if(var.equals(chkEq)) result=val;
  }  
  if(debug)System.out.printf("varToMatrix# %s\n",result);
  return result;
 }

/****************************************************************************************
   METODA ZA PREVERJANJE CE JE PARAMETER STEVILKA (done)
****************************************************************************************/  
 public static boolean isNumber(String tmp) {
  boolean result = false;
  
  if(tmp!=null)tmp=tmp.replaceAll(" ","");
  else return false;
  try { 
   Integer.parseInt(tmp);
   result = true;   
  }
  catch(NumberFormatException nfe) {}
  
  return result;
 }
 
/****************************************************************************************
   METODA ZA PREVERJANJE CE JE MATRIKA 1d - SKALAR (done)
****************************************************************************************/ 
 public static boolean isScalar(String tmp) {
  boolean result=false;
  
  if((getMatrixDimensionX(tmp)==1) && (getMatrixDimensionY(tmp)==1)) 
   result=true;
  
  return result;
 }
 
}

PHP:: FreeBSD uptime status

Since FreeBSD does not have /proc/uptime, there is an equivalent with sysctl. You need to execute an unix command with php, and the third word in the string holds the UNIX timestamp of kernel boot. This function works great with duration() mentioned below.
function uptime() {
 preg_match('#up (.*?) \d+ user#is',exec('uptime'),$a);
 $a = str_replace(',','',$a[1]);
 $a = preg_replace(array('#\:#','#$#'),array(' hours ',' minutes'),$a);
 strtotime("-$a")
 
 $sup = duration($a);
 
 $uptime = "Uptime: $sup";
 
 return $uptime;
}

PHP: calculating time span duration

I needed a function to print a preety time span duration. Nothing special, just simple as that. It turned out to be usefull for many things, like machine (or any other) uptime and so on. Return value is something simmilar to
6 days 3 hours 34 minutes 13 seconds
So here goes, the duration() function. It's published here, so I don't have to waste time and reinvent this everytime.
/*
  Input parameter is the UNIX timestamp 
  of the starting date.
  The second parameter is optional -
  It's value is the ending date,
  also UNIX timestamp. If this
  parameter is not given, the 
  default date is current date.
*/
function duration($start,$end=null) {
 $end = is_null($end) ? time() : $end;

 $seconds = $end - $start;
 
 $days = floor($seconds/60/60/24);
 $hours = $seconds/60/60%24;
 $mins = $seconds/60%60;
 $secs = $seconds%60;
 
 $duration='';
 if($days>0) $duration .= "$days days ";
 if($hours>0) $duration .= "$hours hours ";
 if($mins>0) $duration .= "$mins minutes ";
 if($secs>0) $duration .= "$secs seconds ";
 
 $duration = trim($duration);
 if($duration==null) $duration = '0 seconds';
 
 return $duration;
}