<?php
/**
 * IBSE
 *
 * Information Bot Service Engine
 *
 * @package        IBSE
 * @author        HSDN Team
 * @copyright    Copyright (c) 2006-2010, Information Networks Ltd.
 * @link        http://www.hsdn.org
 * @since        Version 4.0
 */

/**
 * IBAPI
 *
 * Information Bot Application Program Interface
 *
 * @package        IBSE
 * @author        HSDN Team
 * @copyright    Copyright (c) 2006-2010, Information Networks Ltd.
 * @since        Version 4.0
 */

// ------------------------------------------------------------------------

if (defined('LIBRARIES_PATH'))
{
    require_once 
LIBRARIES_PATH.'Lua.inc.php';
}

// ------------------------------------------------------------------------

/**
 * Класс Urq
 *
 * @author        HSDN Team
 *
 * @original    instead-urq
 * @link        http://code.google.com/p/instead-games/
 */
class Urq
{
    public 
$urq = array
    (
        
'debug' => FALSE,
        
'memcached' => 'localhost', // FALSE -- отключить

        
'extension_strings' => TRUE,
        
'extension_furq' => FALSE,
        
'extension_global_else' => FALSE,
        
'extension_input' => TRUE,
        
'extension_useinv' => FALSE, 
        
'extension_loccnt' => TRUE,
        
'extension_loccnt_btn' => TRUE,
        
'extension_invproc' => FALSE,
        
'extension_phantoms' => FALSE,

        
'codepage' => 'cp866',
        
'filename' => '',
        
'cursor' => '>',
        
'last_com' => 'common',
        
'examine' => "Осмотреть",
        
'eol' => "\n",
        
'default_delim' => ' \t,"?!',
        
'ro' => FALSE,
        
'qs1' => FALSE,
        
'save' => FALSE,
        
'btn_exists' => FALSE,
        
'forgetprocs' => FALSE,
        
'ip' => 0,
        
'lastip' => 0,
        
'time' => NULL,
        
'output' => NULL,
        
'input' => NULL,
        
'last_output' => NULL,
        
'last_token' => NULL,
        
'cur_loc' => NULL,
        
'ibranch' => 0,
        
'invo',
        
// 'branches',
        
'stack',
        
'quest' => array(),
        
'strings' => array(),
        
'labels' => array(),
        
'buttons' => array(),
        
'orig_labels' => array(),
        
'use_labels' => array(),
        
'str' => array(),
        
'inv' => array(),
        
'vars' => array
        (
            
'fp_prec' => 2
        
),
    );

    public function 
__construct()
    {
        
// $this->urq['branches'] = new Table(array(), 1);
        
$this->urq['invo'] = new Table(array(), 1);
        
$this->urq['stack'] = new Table(array(), 1);
    }

    public function 
call($cmd, $input = NULL, $real_input = NULL)
    {
        
$r = NULL;
        
$rmode = FALSE;
        
$this->urq['fading'] = FALSE;
        
$this->urq['save'] = FALSE;
        
$this->urq['input'] = $input;

        
$input = $this->lower($input);

        if (
$cmd == 'look') // first run
        
{
            if (isset(
$this->urq['last']) AND $this->urq['last'] != '')
            {
                
$r = $this->urq['last'];
            }
            else
            {
                
$this->start_cmd();

                
$r = $this->exec($this->urq['ip']);

                
$this->urq['last_loc'] = $r;
                
$this->urq['last_output'] = $this->urq['output'];
            }
        }
        else if (
$cmd == 'go') // external
        
{
            if (
$input == 'system')
            {
                if (isset(
$this->urq['vars']['sys']))
                {
                    
$input = $this->lower($this->urq['vars']['sys']);
                }
                else if (isset(
$this->urq['str']['sys']))
                {
                    
$input = $this->lower($this->urq['str']['sys']);
                }
            }

            if ((
$this->urq['last_token'] == 'input')
                OR (
$this->urq['last_token'] == 'pause' 
                    
AND $this->urq['time'] !== NULL 
                    
AND $this->urq['time'] < time())
                )
            {
                
$this->urq['forgetprocs'] = FALSE;

                
$r = $this->exec($this->urq['labels'][$this->urq['cur_loc']]);

                
$this->urq['last_loc'] = $r;
                
$this->urq['last_output'] = $this->urq['output'];
                
$this->urq['last_act'] = NULL;
            }
            else if (isset(
$this->urq['labels'][$input]) 
                AND ((
$this->urq['debug'] === TRUE) ? TRUE : ($this->lower($real_input) != $input OR is_numeric($input))))
            {
                
$this->start_cmd();

                
$r = $this->do_common();

                if (
$this->urq['forgetprocs'] === FALSE) // not in common!
                
{
                    
$this->update_loc($input, TRUE);

                    if (
$this->urq['extension_loccnt_btn'] === TRUE)
                    {
                        
$this->update_count($input);
                    }

                    
$input = $this->urqbtnargs($input);

                    
$this->urq['lastip'] = $this->urq['labels'][$input];

                    
$r = $this->exec($this->urq['lastip'], $input);
                }

                
$this->urq['last_loc'] = $r;
                
$this->urq['last_output'] = $this->urq['output'];
                
$this->urq['last_act'] = NULL;
            }
            else if (isset(
$this->urq['last_loc']))
            {
                
$r = $this->urq['last_loc'];
            }
        }
        if (
$cmd == 'act') // internal
        
{
            
$this->start_cmd();

            if (
$input == 'system')
            {
                if (isset(
$this->urq['vars']['sys']))
                {
                    
$input = $this->urq['vars']['sys'];
                }
                else if (isset(
$this->urq['str']['sys']))
                {
                    
$input = $this->urq['str']['sys'];
                }
            }

            
$this->urq['lastip'] = $this->urq['labels'][$input];

            
$r = $this->exec($this->urq['lastip']);

            
$last_act = isset($this->urq['last_act']) ? $this->urq['last_act'] : '';

            if (
$this->urq['buttons'])
            {
                
$this->last_act = $last_act;
            }

            
$this->reenter();

            
$this->urq['last_act'] = $last_act;
            
$this->urq['last_output'] = $this->urq['output'];
        }
        else if (
$cmd == 'use') // use inv
        
{
            if (
preg_match("/^use_/", $input) AND isset($this->urq['labels'][$input]))
            {
                
$this->start_cmd();

                return 
$this->call('act', $input);
            }

            if (isset(
$this->urq['use_labels']['use_'.$input])) // use
            
{
                
$this->start_cmd();

                return 
$this->call('act', 'use_'.$input);
            }

            
$r = $this->urq['last'];
        }

        if (
$cmd == 'go' 
            
OR $cmd == 'look' 
            
OR $cmd == 'use'
            
OR $cmd == 'act')
        {
            
$this->urq['last'] = $r;
        }

        if (
$this->urq['debug'] === TRUE)
        {
            
$r .= $this->debug($cmd, $input);
        }

        return array
        (
            
'text' => $r,
            
'buttons' => $this->urq_buttons(),
            
'inv' => $this->inv(),
            
'save' => $this->urq['save'],
            
'state' => $this->save_state()
        );
    }

    public function 
error($msg)
    {
        
$this->urq['output'] = 'Error: '.$msg;
    }

    public function 
lower($str)
    {
        return 
mb_strtolower($str, $this->urq['codepage']);
    }

    public function 
debug($cmd, $input)
    {
        return 
"\n"
            
.'[Line: '.$this->urq['ip']
            .
'; token: '.$this->urq['last_token']
            .
'; location: '.$this->urq['cur_loc']
            .(isset(
$this->urq['str']['previous_loc']) ? '; prev location: '.$this->urq['str']['previous_loc'] : '')
            .
'; cmd: '.$cmd
            
.'; input: '.$input.']';
    }

    public function 
take_label($line)
    {
        
$line =  preg_replace("/^:([^&]*)$/i", "\\1", trim($line));

        list(
$loc) = $this->label($line);
        
        return 
$loc;
    }

    public function 
decode_qs1($l)
    {
        
$r = '';

        for (
$i = 0; $i < strlen($l); $i++)
        {
            
$b = $l{$i};

            if (
$b >= chr(32))
            {
                
$b = chr(287 - ord($b));
            }

            
$r .= $b;
        }

        return 
$r;
    }

    function 
load($name)
    {
        
$this->urq['filename'] = $name;

        
$file = file($name);

        if (!
$file)
        {
            return 
FALSE;
        }

        if (
end(explode('.', $name)) == 'qs1')
        {
            
$this->urq['qs1'] = TRUE;
        }

        
$incomment = '';

        
$s = 0;

        foreach (
$file as $line)
        {
            if (
$this->urq['qs1'])
            {
                
$line = $this->decode_qs1($line);
            }

            
$line = str_replace(array("\r", "\n"), '', $line);

            if (
$this->urq['codepage'] == 'cp866' OR $this->urq['codepage'] == 'CP866')
            {
                
$line = mb_convert_encoding($line, 'CP866', 'CP1251');
            }

            
array_push($this->urq['quest'], $line);

            
//$this->urq['quest']->insert($line);

            
$cline = $line = ltrim($line);

            list(
$line, $incomment) = $this->strip_comments($line, $incomment);

            if (
preg_match("/^:/", $line))
            {
                
$line = $this->take_label($line);

                if (!isset(
$this->urq['labels'][$line]) OR $this->urq['labels'][$line] == NULL)
                {
                    
$this->urq['labels'][$line] = end(array_keys($this->urq['quest']));
                    
$this->urq['orig_labels'][$line] = $cline;

                    if (
strpos($line, "use_"))
                    {
                        
$this->urq['use_labels'][$line] = $this->urq['labels'][$line];
                    }
                }
            }
            else if (
preg_match("/^[ \t]*include[ \t]/i", $line))
            {
                list(
$s, $e) = find("include", $line);

                
$f = $this->strip(sub($e + 1));

                
$this->load($f);
            }
        }

        if (
$this->urq['codepage'] == 'cp866' OR $this->urq['codepage'] == 'CP866')
        {
            
$this->urq['examine'] = 'Ћб¬®ваҐвм';
        }
    }

    public function 
label($s)
    {
        if (
$s == NULL)
        {
            return 
NULL;
        }

        
$s = $this->strip($s);

        return array(
$this->lower($s), $s);
    }

    public function 
urqprint($str, $nl = FALSE)
    {
        if (
$str != '')
        {
            
$this->urq['output'] .= $str.' ';
        }

        if (
$nl != FALSE)
        {
            
$this->urq['output'] .= $this->urq['eol'];
        }
    }

    public function 
urqbtnargs($l)
    {
        
$n = 0;
        
$a = '';

        if (
$this->urq['extension_furq'] === TRUE)
        {
            
$num = preg_replace("/^[^;]+;?([0-9]*)$/", "\\1", $l);

            if (
$num != '')
            {
                
$l = preg_replace("/;[0-9]*$/", '', $l);
                
$a = $this->urq['str'][($l.'__urq_btn_arguments__'.((float) $num))];
            }

            
$this->clearbtnargs($l);
        }

        if (
$a == '' OR $this->urq['ro'] === TRUE)
        {
            return 
$l;
        }

        
$this->urq['str'][($l.'__urq_btn_arguments__'.((float) $num))] = NULL;


        if (
$this->urq['extension_strings'] === TRUE)
        {
            
$a = preg_replace('/("[^"]*")/ex', "self::args_reps('\\1')", $a);
        }

        
preg_replace("/([^,]+)/ex", "self::args_subst('\\1', '$l', '$n')", $a);

        return array(
$l, $n);
    }

    public function 
args_subst($s, $l, &$n)
    {
        
$s = $this->strip($s);
        
$s = str_replace('\003', ',', $s);
        
        
$r = $this->urqexpr($s, FALSE, TRUE);

        
$n++;

        if (
is_numeric($r))
        {
            
$this->urq['vars'][$l.'_'.$n] = $r;
        }
        else
        {
            
$this->urq['str'][$l.'_'.$n] = $r;
        }
    }

    public function 
args_reps($s)
    {
        return 
str_replace(',', '\003', $s);
    }

    public function 
clearbtnargs($loc)
    {
        if (
$this->urq['ro'] === TRUE)
        { 
            return;
        }

        foreach (
$this->urq['vars'] as $k => $v)
        {
            if (
preg_match("/^".$loc."_"."[0-9]+/", $k))
            {
                unset(
$this->urq['vars'][$k]);
            }
        }

        foreach (
$this->urq['str'] as $k => $v)
        {
            if (
preg_match("/^".$loc."_"."[0-9]+/", $k))
            {
                unset(
$this->urq['str'][$k]);
            }
        }
    }

    public function 
urqargs($loc)
    {
        list(
$loc, $lloc) = $this->label($loc);

        if (
$this->urq['extension_furq'] === TRUE AND (!isset($this->urq['labels'][$loc]) OR $this->urq['labels'][$loc] == 0))
        {
            
$a = preg_replace("/^[^((]+[((](.*)[))]$/", "\\1", $lloc);
            
$loc = preg_replace("/^([^(]+)[((].*[))]$/", "\\1", $loc);

            
$loc = $this->strip($loc);

            
$this->clearbtnargs($loc);

            
$loca = (string) $this->urq['btn_args'];

            if (
$a != '' AND $this->urq['ro'] === FALSE)
            {
                
$this->urq['str'][$loc.'__urq_btn_arguments__'.$loca] = $a;
            }

            
$this->urq['btn_args']++;

            return array(
$loc, $loc.';'.$loca);
        }

        return array(
$loc, $loc);
    }

    public function 
urqbtn($loc, $str)
    {
        if (
$loc == NULL OR $str == NULL)
        {
            
$this->error("Error in btn at line: ".$this->urq['ip']);
        }

        if (
preg_match('/^[ \t]*$/', $str))
        {
            
$str = '...';
        }

        list(
$loc, $lloc) = $this->urqargs($loc);

        return 
$this->strip($str);
    }

    public function 
urqend()
    {
        return 
$this->urq['output'];
    }

    public function 
urqif($s)
    {
        
$this->urq['ibranch']++;

        
$s = $this->strip($s);

        
$r = (bool) $this->urqexpr($s, TRUE);

        
// $this->urq['branches']->insert($r);

        
return $r;
    }

    public function 
invoidx($a)
    {
        foreach (
$this->urq['invo']->t as $k => $v)
        {
            
$k = $this->lower($k);
            
$v = $this->lower($v);

            if (
$v == $this->lower($this->strip($a)))
            {
                return 
$k;
            }
        }

        return 
NULL;
    }

    public function 
invodel($a)
    {
        if (!
$i = $this->invoidx($a))
        {
            return;
        }

        
$this->urq['invo']->remove($i);
    }

    public function 
invoadd($a)
    {
        
$this->urq['invo']->insert($this->strip($a));
    }

    public function 
urqinvkill($a)
    {
        if (
$this->urq['ro'] === TRUE)
        {
            return;
        }

        if (
$a != '')
        {
            
$a = $this->lower($this->strip($a));

            unset(
$this->inv[$a]);
            unset(
$this->urq['vars']['inv_'.$a]);
            
            
$this->invodel($a);

            return;
        }

        foreach (
$this->urq['inv'] as $k => $v)
        {
            unset(
$this->inv[$k]);
            unset(
$this->urq['vars']['inv_'.$k]);
            
            
$this->invodel($k);
        }
    }

    public function 
urqperkill()
    {
        if (
$this->urq['ro'] === TRUE)
        {
            return;
        }

        foreach (
$this->urq['vars'] as $k => $v)
        {
            if (
preg_match("/^inv_/", $k))
            {
                unset(
$this->urq['vars'][$k]);
            }
        }

        foreach (
$this->urq['str'] as $k => $v)
        {
            if (
preg_match("/^current_loc$/", $k) AND !preg_match("/^previous_loc$/", $k) AND !preg_match("/^last_btn_caption$/", $k))
            {
                unset(
$this->urq['str'][$k]);
            }
        }

        
$this->urq['str']['tokens_delim'] = $this->urq['default_delim'];
        
$this->urq['vars']["fp_prec"] = 2;
    }

    public function 
urqinv($o, $n)
    {
        if (
$this->urq['ro'] === TRUE)
        {
            return;
        }

        if (
$n == NULL OR $o == NULL)
        {
            
$this->error("Error in line: ".$this->urq['ip']);
        }

        
$ob = $this->strip($o);
        
$o = $this->lower($ob);

        if (!isset(
$this->urq['inv'][$o])) // -- make new
        
{
            if (
$n <= 0)
            {
                return;
            }

            
$this->urq['inv'][$o] = array('n' => $n, 'name' => $ob);
            
$this->urq['vars']['inv_'.$o] = $n;

            
$this->invoadd($o);

            return;
        }

        if (isset(
$this->urq['inv'][$o]['n']))
        {
            
$this->urq['inv'][$o]['n'] += $n;
        }

        if (isset(
$this->urq['vars']['inv_'.$o]))
        {
            
$this->urq['vars']['inv_'.$o] += $n;
        }

        if (isset(
$this->urq['inv'][$o]['n']) AND $this->urq['inv'][$o]['n'] <= 0)
        {
            unset(
$this->urq['inv'][$o]);
            unset(
$this->urq['vars']['inv_'.$o]);
            
            
$this->invodel($o);
        }
    }

    public function 
get2args($a)
    {
        if (
strpos($a, ',') !== FALSE)
        {
            list(
$l, $t) = explode(',', $a, 2);

            
$t = trim($t);
        }
        else
        {
            
$l = $a;
            
$t = NULL;
        }

        return array(
trim($l), $t);
    }

    public function 
is_string_pattern($s)
    {
        if (
$s == '')
        {
            return 
FALSE;
        }
        
        if (
preg_match("/^__urq_string__[0-9]+/", $s))
        {
            return 
TRUE;
        }

        return 
FALSE;
    }

    public function 
fprec($n)
    {
        
$prec = $this->urq['vars']["fp_prec"];

        if (!
is_numeric($n))
        {
            
$this->error("Error in expr at line: ".$this->urq['ip']);
        }

        
$n = sprintf('%.'.$prec.'f', $n); // ?

        
return (float) $n;
    }

    public function 
check_inv($s)
    {
        if (isset(
$this->urq['inv'][$s]) AND $this->urq['inv'][$s] != '')
        {
            return 
1;
        }

        
$n = preg_match("/^([^ \t]+)[ \t][^ \t]+$/", "\\1", $s);
        
$i = preg_match("/^[^ \t]+[ \t]([^ \t]+)$/", "\\1", $s);

        if (
is_numeric($n) AND $i)
        {
            if (isset(
$this->urq['inv'][$i]) AND $this->urq['inv'][$i] != '')
            {
                
$i = $this->urq['inv'][$i][$n];
            }
            else
            {
                
$i = 0;
            }

            return 
$n.'<='.$i;
        }

        return 
NULL;
    }

    public function 
urqvar($v, $inif) // only numeric!
    
{
        
$n = NULL;

        
$s = $this->lower($this->strip($v));

        
$rnd = (float) mt_rand(0, 10000) / 10000;

        if (
$s == 'rnd')
        {
            return 
$this->fprec($rnd);
        }
        if (
preg_match("/^rnd([0-9]+)$/", $s, $r))
        {
            
$n = ($r[1] > 0) ? intval(mt_rand(0, $r[1])) : $rnd;

            return 
$this->fprec($n);
        }
        else if (
$s == 'time')
        {
            return 
$this->fprec(time());
        }
        else
        {
            if (isset(
$this->urq['vars'][$s]) AND $this->urq['vars'][$s] != NULL) // numeric
            
{
                
$n = $this->urq['vars'][$s];
            }
            else if (isset(
$this->urq['str'][$s]) AND $this->urq['str'][$s] != NULL) // string
            
{
                
$n = $this->urq['str'][$s];
            }
            else if (isset(
$this->urq['vars']['inv_'.$s]) AND $this->urq['vars']['inv_'.$s] != NULL) // inv
            
{
                
$n = $this->urq['vars']['inv_'.$s];
            }
            else if (
$inif === TRUE)
            {
                
$r = $this->check_inv($s);

                if (
$r != NULL)
                {
                    return 
$r;
                }
            }
        }

        if (
$n == NULL)
        {
            return 
0;
        }
    
        if (!isset(
$this->urq['vars'][$s]) OR $this->urq['vars'][$s] == NULL)
        {
            
$n = (string) strlen($n);
        }

        return 
$this->fprec($n);
    }

    public function 
urqstr($s)
    {
        if (
$s == '')
        {
            
$this->error("Error in line: ".$this->urq['ip']);
        }

        
$s = $this->lower($this->strip($s));

        if (!isset(
$this->urq['str'][$s]) OR $this->urq['str'][$s] == '')
        {
            return 
'';
        }

        return (string) 
$this->urq['str'][$s];
    }

    public function 
add_string($r)
    {
        if (
$p = in_array($r, $this->urq['strings']))
        {
            return 
'__urq_string__'.$p;
        }

        
array_push($this->urq['strings'], $r);

        return 
'__urq_string__'.end(array_keys($this->urq['strings']));
    }

    public function 
urqexpr($str, $inif = FALSE) // already substed
    
{
        
$str = $this->strip($str);

        if (
$this->urq['extension_strings'] === TRUE)
        {
            
$str = preg_replace('/"([^\"]*)\"/ex', "self::expr_reps('\\1')", $str);
        }

        
$str = 
            
preg_replace("/^([ \t]*)not([ \t((])/", "\\1(!)\\2",
            
preg_replace("/([ \t))((])not([ \t(())])/", "\\1(!)\\2",
            
preg_replace("/([ \t))((])or([ \t(())])/", "\\1(||)\\2", 
            
preg_replace("/([ \t))((])and([ \t(())])/", "\\1(&&)\\2", 
            
$this->lower($str)))));

        
$str = preg_replace("#([^+\^\=/\*/>><<))((-]+)#ex", "self::expr_rep('\\1', '$inif')", $str);

        
$str = 
            
preg_replace("/[\(\(]![\)\)]/", "!",
            
preg_replace("/[\(\(]&&[\)\)]/", "&&", 
            
preg_replace("/[\(\(]\|\|[\)\)]/", "||", $str)));

        
$expr = new Expr($this->urq['strings']);

        
$r = $expr->call($str);

        if (
$r === NULL)
        {
            
$this->error("Error in expression at line: ".$this->urq['ip']);
        }

        return 
$r;
    }

    public function 
expr_reps($s)
    {
        
$s =  preg_replace('/"[ \t]*$/', '', ltrim($s));
        
        return 
$this->add_string($s);
    }

    public function 
expr_rep($s, $inif)
    {
        
$s = $this->strip($s);

        if (
$this->is_string_pattern($s) OR preg_match("/^[ \t]*$/", $s))
        {
            return 
$s;
        }

        if (
$s == '&&' OR $s == '||' OR $s == '!')
        {
            return 
$s;
        }

        if (
is_numeric($s))
        {
            return 
$s; // number as is
        
}

        if (isset(
$this->urq['str'][$this->lower($s)]) AND $this->urq['str'][$this->lower($s)] != NULL)
        {
            return 
$this->add_string($this->urq['str'][$this->lower($s)]);
        }

        return 
$this->urqvar($s, $inif); // last
    
}

    public function 
urqlet($l, $r, $str = FALSE)
    {
        if (
$this->urq['ro'] === TRUE)
        {
            return;
        }

        
$l = $this->strip($l);

        if (
$str == FALSE 
            
OR !isset($this->urq['vars']['instr_leave_spc']) 
            OR 
$this->urq['vars']['instr_leave_spc'] == NULL)
        {
            
$r = $this->strip($r);
        }

        if (
$r === NULL)
        {
            
$this->error("No right value at line: ".$this->urq['ip']);
        }

        
$v = $this->lower($l);

        if (
$str !== FALSE)
        {
            
$this->urq['str'][$v] = $r;
            unset(
$this->urq['vars'][$v]);
            
            return;
        }

        
$res = $this->urqexpr($r);

        if (
is_numeric($res))
        {
            
$this->urq['vars'][$v] = $res;
            unset(
$this->urq['str'][$v]);
        }
        else
        {
            
$this->urq['str'][$v] = $res;
            unset(
$this->urq['vars'][$v]);
        }

        if (
preg_match("/^inv_/", $v))
        {
            
$o = sub($l, 5);

            if (isset(
$this->urq['inv'][$o]))
            {
                
$this->urq['inv'][$o]['n'] = (float) $this->urq['vars'][$v];
            }
            else
            {
                
$this->urqinv($o, ((float) $this->urq['vars'][$v]));
            }
        }
    }

    public function 
subst($str, $eval = FALSE)
    {
        
$l = $i = $k = 0;
        
$depth = 0;
        
$s = '';

        if (
$str === '')
        {
            return;
        }

        list(
$i) = find($str, '[#$$]');

        while (
$i)
        {
            if ((
sub($str, $i, $i) == '#') AND ($i == 1 OR sub($str, $i - 1, $i - 1) != '#'))
            {
                
$depth++;

                if (
$depth == 1)
                {
                    
$s = $i + 1;
                }
            }
            else if (
sub($str, $i, $i) == '$')
            {
                
$depth--;

                if (
$depth < 0)
                {
                    return 
$str; // no pairs
                
}

                if (
$depth == 0)
                {

                    
$r = $this->subst(sub($str, $s, $i - 1), TRUE);

                    
$str = sub($str, 1, $s - 2).$r.sub($str, $i + 1);

                    
$i = $s - 2 + strlen($r);
                }
            }

            list(
$i) = find($str, '[#$$]', $i + 1);
        }

        if (
$eval == TRUE)
        {
            if (
preg_match("/^[ \t]*$/", $str))
            {
                
$str = ' ';
            }
            else if (
preg_match("#^[ \t]*/[ \t]*#", $str))
            {
                
$str = $this->urq['eol'];
            }
            else if (
preg_match("/^%/", $str))
            {
                
$str = $this->urqstr(sub($str, 2));
            }
            else if (
preg_match("/^#/", $str))
            {
                
$c = (int) $this->strip(sub($str, 2));

                if (
$c <= 255)
                {
                    
$str = chr($c);
                }
            }
            else
            {
                
$str = $this->urqexpr($str);

                if (!
is_numeric($str))
                {
                    
$str = strlen($str);
                }
            }
        }

        return 
$str;
    }

    public function 
strip($s)
    {
        return 
preg_replace("/[ \t]+$/", '', ltrim($s));
    }

    public function 
strip_comments($line, $incomment)
    {
        if (
$incomment != '')
        {
            list(
$s, $e) = find($line, "*/", 1, TRUE);
            
            if (
$e !== NULL)
            {
                
$incomment = FALSE;

                
$line = sub($line, $e + 1);
            }
            else
            {
                
$line = '';
            }
        }

        while (
TRUE)
        {
            list(
$s, $e) = find($line, "/*", 1, TRUE);

            if (
$s === NULL)
            {
                break;
            }

            list(
$ss, $ee) = find($line, "*/", $e + 1, TRUE);

            if (
$ss === NULL)
            {
                
$incomment = TRUE;
                
$line = sub($line, 1, $s - 1);

                break;
            }

            
$line = sub($line, 1, $s - 1).sub($line, $ee + 1);
        }

        
$line = preg_replace("/^([^;]*);.*$/", "\\1", $line);

        return array(
$line, $incomment);
    }

    public function 
update_count($l)
    {
        if (
$this->urq['ro'] === TRUE)
        {
            return;
        }

        if (
$this->urq['extension_loccnt'] === TRUE)
        {
            
$l = 'count_'.$l;
        }

        if (!isset(
$this->urq['vars'][$l]))
        {
            
$this->urq['vars'][$l] = 0;
        }

        
$this->urq['vars'][$l]++;
    }

    public function 
token_add($r, $n)
    {
        if (
preg_match("/^[ \t]*$/", $r))
        {
            return 
$n;
        }

        
$n++;

        
$this->urqlet('token'.$n, $r, TRUE);

        return 
$n;
    }

    public function 
find_delim($a, $d)
    {
        
$se = NULL;
        
$i = 1;

        while (
$i <= strlen($d))
        {
            if (
$d == 'char')
            {
                return array(
1, 1);
            }

            
$c = sub($d, $i, $i);
            
$s = find($a, $c, 1, TRUE);

            if (
$se === NULL OR ($s !== NULL and $s < $se))
            {
                
$se = $s;
            }

            
$i++;
        }

        return array(
$se, $se);
    }

    public function 
destroy_tokens()
    {
        foreach (
$this->urq['str'] as $k => $v)
        {
            if (
preg_match("/^token[0-9]+$/", $k))
            {
                
$v = NULL;
            }
        }
    }

    public function 
urqtokens($a)
    {
        if (
$this->urq['ro'] === TRUE)
        {
            return;
        }

        if (
$a == '')
        {
            
$this->error("Tokens without argument in line: ".$this->urq['ip']);
        }

        
$delim = $this->urq['str']['tokens_delim'];

        if (
$delim == '')
        {
            
$delim = $this->urq['default_delim'];
        }

        
$n = 0;
        
        
$this->destroy_tokens();

        do
        {
            list(
$s) = $this->find_delim($a, $delim);

            if (
$s === NULL)
            {
                
$r = sub($a, 1);
                
$n = $this->token_add($r, $n);
                
                break;
            }

            if (
1 != $s)
            {
                
$r = sub($a, 1, (int) $s - 1);
                
$n = $this->token_add($r, $n);
            }
            else if (
$delim == 'char')
            {
                
$r = sub($a, 1, 1);
                
$n = $this->token_add($r, $n);
            }

            
$a = sub($a, (int) $s + 1);
        }
        while ((list(
$u) = find($a, "^[ \t]*$")) AND $u !== NULL); // ???

        
$this->urq['vars']["tokens_num"] = (int) $n;
    }

    function 
update_loc($l, $btn = '')
    {
        if (
$this->urq['ro'] === TRUE)
        {
            return;
        }

        if (
$l == '')
        {
            return;
        }

        
$c = isset($this->urq['str']['current_loc']) ? $this->urq['str']['current_loc'] : '';

        if (
$btn != '' AND $c != $l)
        {
            
$this->urq['str']['previous_loc'] = $c;
            
$this->urq['str']['current_loc'] = $l;
        }

        
$this->urq['cur_loc'] = $l;
    }

    public function 
findif($line)
    {
        list(
$s, $e) = find($this->lower($line), "[))& \t]if[ \t((]");

        if (
$s !== NULL)
        {
            list(
$s, $e) = find($this->lower($line), "if", $s);
        }

        return array(
$s, $e);
    }

    public function 
findthen($line)
    {
        list(
$s, $e) = find($this->lower($line), "[))& \t]then[ \t((]");

        if (
$s !== NULL)
        {
            list(
$s, $e) = find($this->lower($line), "then", $s);
        }

        return array(
$s, $e);
    }

    public function 
findifelse($line)
    {
        list(
$s, $e) = $this->findif($line);

        if (
$this->urq['extension_global_else'] === TRUE)
        {
            list(
$ss, $ee) = find($this->lower($line), "else");
        }
        else
        {
            list(
$ss, $ee) = find($this->lower($line), "[$$))& \t]else[ \t((]");
        }

        if (
$ss !== NULL)
        {
            list(
$ss, $ee) = find($this->lower($line), "else", $ss);
        }

        if (
$s !== NULL AND $ss !== NULL)
        {
            if (
$s <= $ss)
            {
                return array(
$s, $e, TRUE);
            }

            return array(
$ss, $ee, NULL);
        }

        if (
$s === NULL)
        {
            return array(
$ss, $ee, NULL);
        }
        
        return array(
$s, $e, TRUE);
    }

    public function 
findelse($line)
    {
        
$pos = 0;
        
$inif = 0;

        while (
TRUE)
        {
            list(
$s, $e, $i) = $this->findifelse($line);

            if (
$i !== NULL)
            {
                
$inif++; 
            }
            else
            {
                if (
$s === NULL)
                {
                    return array(
NULL, NULL);
                }

                if (
$inif == 0)
                {
                    return array(
$pos + $s, $pos + $e);
                }

                
$inif--;
            }

            
$line = sub($line, $e + 1);

            
$pos += $e;
        }
    }

    public function 
pushcall()
    {
        
$this->urq['stack']->insert($this->urq['ip']);
        
$this->urq['stack']->insert($this->urq['depth']);
    }

    public function 
popcall()
    {
        
$this->urq['stack']->remove($this->urq['stack']->maxn());
        
$this->urq['stack']->remove($this->urq['stack']->maxn());
    }

    public function 
exec($ip, $tolabel = '')
    {
        
$ret = NULL;

        if (
$ip > sizeof($this->urq['quest'])) 
        {
            
$this->error("Error while exec wrong line. ");
        }

        
$this->update_loc($tolabel);

        
$incomment = '';

        while (
$ip <= sizeof($this->urq['quest']) AND $ret == '')
        {
            
$this->urq['ip'] = $ip;
            
$line = $this->urq['quest'][$ip];
            
$line = ltrim($line);

            list(
$line, $incomment) = $this->strip_comments($line, $incomment);

            while (
$ip < sizeof($this->urq['quest']) AND isset($this->urq['quest'][$ip + 1]) AND preg_match("/^[ \t]*_+/", $this->urq['quest'][$ip + 1])) // concat lines
            
{
                
$ip++;

                
$line = $line.preg_replace("/^[ \t]*_+/", '', $this->urq['quest'][$ip]);

                list(
$line, $incomment) = $this->strip_comments($line, $incomment);
            }

            
$this->urq['ip'] = $ip;
            
$this->urq['depth'] = 1;

            list(
$line, $incomment) = $this->strip_comments($line, $incomment);

            while (
$line !== '')
            {
                
$line = ltrim(preg_replace("/^&+/", "", $line));

                list(
$s, $e) = find($line, "&");


                if (
$s !== NULL) // get line before &
                
{
                    
$sline = $this->subst(sub($line, 1, $e - 1));
                }
                else
                {
                    
$sline = $this->sline = $this->subst($line);
                }

                list(
$i, $k) = find($sline, "[ \t]");

                if (
$i !== NULL)
                {
                    
$cmd = ltrim(sub($sline, 1, $i - 1));
                    
$a = sub($sline, $i + 1);
                }
                else
                {
                    
$cmd = $this->strip($sline);
                    
$a = NULL;
                }

                
$cmd = $this->lower($cmd);

                
//echo $cmd.' ';

                
$this->urq['last_token'] = $cmd;

                if (
preg_match("/^:/", $line))
                {
                    
// noting todo
                    
$l = $this->take_label($line);

                    if (
$this->urq['extension_loccnt_btn'] === FALSE)
                    {
                        
$this->update_count($l);
                    }

                    if (!isset(
$this->urq['str']['current_loc']) 
                        OR !isset(
$this->urq['str']['previous_loc']) 
                        OR 
$this->urq['str']['current_loc'] == NULL 
                        
OR $this->urq['str']['previous_loc'] == NULL)
                    {
                        
$this->update_loc($l, TRUE);
                    }
                }
                else if (
$cmd == 'include')
                {
                    
// nothing todo
                
}
                else if (
$cmd == 'inv_visible' OR $cmd == 'html')
                {
                    
// nothing todo
                
}
                else if (
$cmd == 'clsb')
                {
                    if (
$this->urq['extension_input'] === TRUE)
                    {
                        
$this->urq['buttons'] = NULL;
                    }
                }
                else if (
$cmd == 'cls' OR $cmd == 'clst')
                {
                    if (
$this->urq['extension_input'])
                    {
                        
$this->urq['output'] = '';
                        
$this->urq['buttons'] = NULL;
                    }
                }
                else if (
$cmd == 'input')
                {
                    
$a = $this->lower($a);

                    if (
$this->urq['ro'] === FALSE 
                        
AND $a != ''
                        
AND $this->urq['extension_input'] === TRUE)
                    {
                        if (
$this->urq['input'] === NULL)
                        {
                            
$this->urq['forgetprocs'] = TRUE;
                            
$this->urq['output'] .= "\n".$this->urq['cursor'];

                            
$ret = TRUE;

                            break;
                        }
                        else
                        {
                            if (isset(
$this->urq['str'][$a]) OR !is_numeric($this->urq['input']))
                            {
                                
$this->urq['str'][$a] = $this->urq['input'];
                            }
                            else
                            {
                                
$this->urq['vars'][$a] = $this->urq['input'];
                            }

                            
$this->urq['input'] = NULL;
                            
$this->urq['output'] = '';
                        }
                    }
                }
                else if (
$cmd == 'p' OR $cmd == 'print')
                {
                    
$this->urqprint($a);
                }
                else if (
$cmd == 'pln' OR $cmd == 'println')
                {
                    
$this->urqprint($a, TRUE);
                }
                else if (
$cmd == 'quit')
                {
                    
$this->urq['forgetprocs'] = TRUE; // todo?
                    
$ret = TRUE;
                    
                    break;
                }
                else if (
$cmd == 'end')
                {
                    
$this->urq['btn_exists'] = FALSE;
                    
$ret = TRUE;

                    break;
                }
                else if (
$cmd == 'invkill')
                {
                    
$this->urqinvkill($a);
                }
                elseif (
$cmd == 'perkill')
                {
                    
$this->urqperkill();
                }
                else if (
$cmd == 'inv+')
                {
                    list(
$l, $t)  = $this->get2args($a);

                    if (
$t === NULL)
                    {
                        
$t = 1;
                    }
                    else
                    {
                        list(
$l, $t) = array($t, $l);
                    }
                    
                    if (
$this->urq['extension_furq'])
                    {
                        
$t = $this->urqexpr($t);
                    }

                    
$this->urqinv($l, $t);
                }
                else if (
$cmd == 'inv-')
                {
                    list(
$l, $t)  = $this->get2args($a);

                    if (
$t === NULL)
                    {
                        
$t = 1;
                    }
                    else
                    {
                        list(
$l, $t) = array($t, $l);
                    }

                    if (
$this->urq['extension_furq'])
                    {
                        
$t = $this->urqexpr($t);
                    }

                    if (
intval($t) == 0)
                    {
                        
$t = 1;
                        
                        
// print ("Warning: wrong number in inv-.");
                    
}

                    
$this->urqinv($l, -$t);
                }
                else if (
$cmd == 'btn')
                {
                    
$l = NULL;
                    
$t = 0;
                    
                    if (
$this->urq['extension_furq'] === TRUE)
                    {
                        list(
$s, $e) = find("^[^((]+[((].*[))],", $a);

                        if (
$e !== NULL)
                        {
                            
$l = sub($a, 1, $e - 1); 
                            
$t = sub($a, $e + 1);
                        }
                    }

                    if (
$l == NULL)
                    {
                        list(
$l, $t) = $this->get2args($a);
                    }

                    
$this->urq['btn_exists'] = TRUE;

                    if (
$l == 'system')
                    {
                        if (isset(
$this->urq['vars']['sys']))
                        {
                            
$l = $this->urq['vars']['sys'];
                        }
                        else if (isset(
$this->urq['str']['sys']))
                        {
                            
$l = $this->urq['str']['sys'];
                        }
                    }

                    if (isset(
$this->urq['labels'][$this->lower($l)]))
                    {
                        
$this->urq['buttons'][$l] = $this->urqbtn($l, $t);
                    }
                    else if (
$this->urq['extension_phantoms'] === TRUE)
                    {
                        
$this->urq['buttons'][$l] = $this->urqbtn($l, $t).' //phantom';
                    }
                }
                else if (
$cmd == 'forget_procs')
                {
                    
$this->urq['forgetprocs'] = TRUE;
                }
                else if (
$cmd == 'proc')
                {
                    
$a = preg_replace("/[ \t]+$/", '', $a);

                    list(
$a, $lloc) = $this->urqargs($a);

                    if (!isset(
$this->urq['labels'][$a]) OR $this->urq['labels'][$a] == NULL)
                    {
                        
//print ("proc on non existing label '".$a."' at line: ".$ip);
                    
}
                    else if (
gettype($this->urq['labels'][$a]) == 'object') // ???
                    
{
                        
$a = $this->urqbtnargs($lloc);

                        
$func = $this->urq['labels'][$a];

                        
$this->$func();
                    }
                    else
                    {
                        
$a = $this->urqbtnargs($lloc);

                        
$this->pushcall();

                        if (
$tolabel)
                        {
                            
$this->exec($this->urq['labels'][$a], $a);
                        }
                        else
                        {
                            
$this->exec($this->urq['labels'][$a]);
                        }

                        
$this->popcall();

                        if (
$this->urq['forgetprocs'] === TRUE)
                        {
                            
$ret = TRUE;
                        }
                        else
                        {
                            
$this->update_loc($tolabel);
                        }
                    }
                }
                else if (
$cmd == 'tokens')
                {
                    if (
$a != '')
                    {
                        
$a = $this->urq['str'][$this->strip($this->lower($a))];
                    }

                    
$this->urqtokens($a);
                }
                else if (
$cmd == 'goto' OR $cmd == 'save')
                {
                    
$this->urq['time'] = NULL;

                    if (
$cmd == 'save')
                    {
                        if (
$a != '')
                        {
                            
$this->autosave($a);
                        }
                        else
                        {
                            
$this->autosave($this->urq['cur_loc']);
                        }
                    }

                    if (
$a != '')
                    {
                        
$a = preg_replace("/[ \t]+$/", '', $a);
                        
                        list(
$a, $lloc) = $this->urqargs($a);

                        if (
$a != $this->urq['cur_loc']) // защита от зацикливания (loop-методы работать не будут!)
                        
{
                            if (!isset(
$this->urq['labels'][$a]) OR $this->urq['labels'][$a] == NULL)
                            {
                                
//print ("goto on non existing label '".$a."' at line: ".$ip);
                            
}
                            else
                            {
                                
$a = $this->urqbtnargs($lloc);

                                if (
$tolabel != '')
                                {
                                    
$tolabel = $a;
                                }

                                
$this->exec($this->urq['labels'][$a], $tolabel);

                                
$ret = TRUE;
                            }
                        }
                    }
                }
                else if (
$cmd == 'music' OR $cmd == 'play' OR $cmd == 'image' OR $cmd == 'anykey')
                {
                    
// skip
                
}
                else if (
$cmd == 'pause')
                {
                    if (
$this->urq['btn_exists'] === TRUE AND $a != 0)
                    {
                        if (
$this->urq['time'] === NULL)
                        {
                            
$this->urq['time'] = time() + floor($a / 1000);
                        }

                        if (
$this->urq['time'] >= time())
                        {
                            if (
$this->urq['input'] !== NULL)
                            {
                                
$this->urq['output'] = $this->urq['last'];
                            }

                            
$ret = TRUE;

                            break;
                        }

                        
$this->urq['btn_exists'] = FALSE;
                    }

                    
$this->urq['time'] = NULL;
                }
                else if (
$cmd == 'else')
                {
                    break;
                }
                else if (
$cmd == 'if')
                {
                    list(
$i, $k) = $this->findthen($a);

                    if (
$i === NULL)
                    {
                        
$this->error('if without then at line: '.$ip.' ('.$a.')');
                    }

                    
$a = sub($a, 1, $i - 1);

                    if (!
$this->urqif($a))
                    {
                        list(
$i, $k) = $this->findelse($line);

                        if (
$i !== NULL)
                        {
                            list(
$s, $e) = array($i, $k);
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        list(
$i, $k) = $this->findelse($line);

                        if (
$i !== NULL)
                        {
                            
$line = sub($line, 1, $i - 1);
                        }

                        list(
$s, $e) = $this->findthen($line);
                    }
                }
                else if (
$cmd  == 'instr')
                {
                    list(
$l, $r) = explode('=', $a, 2);

                    
$this->urqlet($l, $r, TRUE);
                }
                else if (
strpos($sline, '=') !== FALSE)
                {
                    list(
$l, $r) = explode('=', $sline, 2);

                    
$this->urqlet($l, $r);
                }
                else
                {
                    if (
$this->urq['extension_furq'] AND 
                    (
                           
preg_match("/^decor_/", $cmd)
                        OR 
preg_match("/^decoradd/", $cmd)
                        OR 
preg_match("/^decordel/", $cmd)
                        OR 
preg_match("/^decorcol/", $cmd)
                        OR 
preg_match("/^decorrot/", $cmd)
                        OR 
preg_match("/^decormov/", $cmd)
                    ))
                    {
                        
// skip
                    
}
                    else if (
$cmd != '')
                    {
                        
//print ("Unknown cmd in line: ".$this->urq['ip']." cmd: ".$sline."\n");
                    
}
                }

                if (
$e != '')
                {
                    
$line = ltrim(sub($line, $e + 1));
                }
                else
                {
                    
$line = '';
                }

                
$this->urq['depth']++;
            }

            
$ip++;
        }

        
$ret = $this->urqend();

        
$this->urq['ip'] = $ip;

        
$ret = preg_replace("/[\n]+$/", "\n", preg_replace("/^[ \t]*[\n]+/", '', $ret));

        return 
$ret;
    }

    public function 
idisp($o)
    {
        if (isset(
$this->urq['str']['idisp_'.$this->lower($o)]) 
            AND 
$this->urq['str']['idisp_'.$this->lower($o)] != NULL 
            
AND $this->urq['extension_furq'] === TRUE)
        {
            
$o = $this->urq['str']["idisp_".$this->lower($o)];
        }

        
$o = str_replace("_", " ", $o);

        return 
$o;
    }

    public function 
inv()
    {
        
$r = array();

        if (
$this->urq['extension_useinv'] === TRUE)
        {
            foreach (
$this->urq['use_labels'] as $k => $v)
            {
                if (
preg_match("/^use_inv$/", $k))
                {
                    
$d = $this->urq['orig_labels'][$k];

                    if (
$d !='')
                    {
                        
$this->error("Fatal error in: ".$this->urq['ip']);
                    }

                    
$r[$k] = $this->urq['examine'];
                }
            }
        }

        foreach (
$this->urq['use_labels'] as $k => $v)
        {
            list(
$s, $e) = find("^use_inv_.*$", $k);

            if (
$s !== NULL)
            {
                if (!isset(
$this->urq['orig_labels'][$k]) OR $this->urq['orig_labels'][$k] == '')
                {
                    
$this->error("Fatal error in: ".$this->urq['ip']);
                }

                
$d = $this->urq['orig_labels'][$k];

                
$r[$k] = $this->idisp(sub($d, 9));
            }
        }

        foreach (
$this->urq['invo']->t as $kk => $vv)
        {
            
$k = $this->lower($this->strip($vv));
            
$v = $this->urq['inv'][$k];

            if (
is_array($v))
            {
                
$pre = '';

                if (
$v['n'] > 1)
                {
                    
$pre = $this->fprec($v['n']).' ';
                }

                
$r[$k] = $pre.$this->idisp($v['name']);
            }
        }

        return 
$r;
    }

    public function 
urq_buttons()
    {
        
$ret = $this->urq['buttons'];

        if (
$ret == NULL)
        {
            return;
        }
        
        
$ret = preg_replace("/[\n]+$/", "\n", preg_replace("/^[ \t]*[\n]+/", "\n", $ret));

        return 
$ret;
    }

    public function 
start_cmd()
    {
        
$this->urq['input'] = NULL;
        
$this->urq['output'] = '';
        
$this->urq['buttons'] = NULL;
        
$this->urq['forgetprocs'] = FALSE;
        
$this->urq['btn_args'] = 1;
    }

    public function 
reenter()
    {
        
$cur_loc = $this->urq['cur_loc'];

        if (
$this->urq['extension_invproc'] === FALSE OR $cur_loc == '')
        {
            return;
        }

        
$ip = $this->urq['labels'][$cur_loc];

        
$this->start_cmd();

        
$this->urq['ro'] = TRUE;
        
$this->urq['last_loc'] = $this->exec($ip);
        
$this->urq['ro'] = FALSE;
        
$this->urq['output'] = NULL;
        
$this->urq['input'] = NULL;
    }

    public function 
do_common()
    {
        
$r = '';

        if (isset(
$this->urq['vars']['common']) AND $this->urq['vars']['common'] != '')
        {
            
$com = 'common_'.$this->urq['vars']['common'];
        }
        else
        {
            
$com = 'common';
        }

        if (isset(
$this->urq['labels'][$com]) 
            AND isset(
$this->urq['str']['last_btn_caption'])
            AND 
$this->urq['labels'][$com] != NULL 
            
AND $this->urq['str']['last_btn_caption'] != '') // not init
        
{
            
$r = $this->exec(preg_replace("/[\n]+$/", '', $this->urq['labels'][$com]));
        }

        
$this->urq['last_com'] = $com;

        return 
$r;
    }

    public function 
autosave($loc)
    {
        
$this->urq['save'] = $this->lower($loc);
    }

    public function 
save_state()
    {
        if (
$this->urq['memcached'] !== FALSE)
        {
            
$m = new Memcached();

            
$m->addServer($this->urq['memcached'], 11211);
            
$m->set(md5($this->urq['filename']), $this->urq['quest']);

            unset(
$this->urq['quest']); // не заливать в БД
        
}

        
$urq = $this->urq;

        
/*if ($this->urq['save'] != '' AND isset($this->urq['labels'][$this->urq['save']]))
        {
            $urq['ip'] = $this->urq['labels'][$this->urq['save']];
            $urq['cur_loc'] = $this->urq['save'];
            $urq['last'] = '';
            //var_dump($urq['ip'] );
        }*/

        
return array
        (
            
'urq' => $urq
        
);
    }

    public function 
load_state($state_array)
    {
        if (
is_array($state_array) AND sizeof($state_array) > 0)
        {
            if (
$this->urq['memcached'] !== FALSE)
            {
                
$m = new Memcached();

                
$m->addServer($this->urq['memcached'], 11211);

                
$state_array['urq']['quest'] = $m->get(md5($state_array['urq']['filename']));
            }

            
$this->urq = $state_array['urq'];
        }
    }
}

/* EOF Urq.class.php */