<?php

class escapeConverter
{
  function convertHex($c)
  {
    if(ord($c) >= ord('0') && ord($c) <= ord('9'))
      {
        return ord($c)-ord('0');
      }
    if(ord($c) >= ord('a') && ord($c) <= ord('f'))
      {
        return ord($c)-ord('a')+10;
      }
    return ord($c)-ord('A')+10;
  }

  function convertHexValue($c1, $c2)
  {
    $byte = ($this->convertHex($c1) << 4) + $this->convertHex($c2);
    return chr($byte);
  }

  function convertUnicode($c1, $c2, $c3, $c4)
  {
    $highByte = ($this->convertHex($c1) << 4) + $this->convertHex($c2);
    $lowByte = ($this->convertHex($c3) << 4) + $this->convertHex($c4);
    $dec = ($highByte << 8 | $lowByte);
    return chr($dec);
  }

  function isHexChar($c)
  {
    if( (ord($c) >= 48 && ord($c) <= 57) || //0-9
        (ord($c) >= 65 && ord($c) <= 70) || //A-F
        (ord($c) >= 97 && ord($c) <= 102) //a-f
        )
      {
        return true;
      }
    return false;
  }

  function unescape($str)
  {
    $output = "";
    $length = strlen($str);

    for($i = 0; $i < $length; $i++)
      {
        if($str[$i] === '\\' && $i+5 < $length)
          {
            if($str[$i+1] === 'u' &&
               $this->isHexChar($str[$i+2]) &&
               $this->isHexChar($str[$i+3]) &&
               $this->isHexChar($str[$i+4]) &&
               $this->isHexChar($str[$i+5]))
              {
                $output .= $this->convertUnicode($str[$i+2], $str[$i+3], $str[$i+4], $str[$i+5]);
                $i += 5;
                continue;
              }
          }
        if($str[$i] === '%' && $i+2 < $length)
          {
            if($this->isHexChar($str[$i+1]) && $this->isHexChar($str[$i+2]))
              {
                $output .= chr(hexdec($str[$i+1].$str[$i+2]));
                //this could also be done as output .= chr(hexdec($str[$i+1].$str[$i+2]));
                //$output .= $this->convertUnicode('0', '0', $str[$i+1], $str[$i+2]);
                $i += 2;
                continue;
              }
          }
        $output .= $str[$i];
      }
    return $output;
  }
}

//output should be: %z1a\u00zfaz
$data = "%z1%61\\u00zf\\u0061z";
$u = new escapeConverter();
echo "data: " . $u->unescape($data)."\n";
?>