<?php
/**
 * YANA library
 *
 * @package yana
 * @licence http://creativecommons.org/licenses/by-nc-sa/2.5/
 *
 * @ignore
 */

/**
 * «utility» DisplayUtility
 *
 * This is a utility class. It encapsulates extensions to use with
 * the smarty temlate engine.
 *
 * {@internal
 *
 * Additional smarty functions and modifiers are documented elsewhere.
 * This file should be ignored in API-documentation.
 *
 * }}
 *
 * @static
 * @access      public
 * @package     yana
 * @subpackage  core
 *
 * @ignore
 */
class DisplayUtility
{

    /**
     * toTimestamp
     *
     * converts input created by usage of the smarty functions
     * "html_select_time" and "html_select_date" to a UNIX-Timestamp
     *
     * @access  public
     * @static
     * @param   string  $prefix
     * @param   array   $ARGS
     * @return  int
     */
    function toTimestamp($prefix, $ARGS)
    {
        return mktime((int) @$ARGS[$prefix.'hour'], (int) @$ARGS[$prefix.'minute'], (int) @$ARGS[$prefix.'second'], (int) @$ARGS[$prefix.'month'], (int) @$ARGS[$prefix.'day'], (int) @$ARGS[$prefix.'year']);
    }

    /**
     * «smarty function» guiCreate
     *
     * <pre>
     * This function takes the following arguments:
     *
     * string  $template        (mandatory) template that should be used (view_seperated, view, new, edit, search)
     * string  $file            (mandatory) path and name of structure file
     * string  $table           (mandatory) table to choose from structure file
     * string  $where           (optional)  sequence for SQL-where clause <FIELDNAME1>=<VALUE1>[,<FIELDNAME2>=<VALUE2>[,...]]
     * string  $sort            (optional)  name of column to sort entries by
     * boolean $desc            (optional)  sort entries descendant (true) or ascendant (false)
     * integer $page            (optional)  number of 1st entry to show
     * integer $entries         (optional)  number of entries to show
     * boolean $titles          (optional)  should fieldnames be shown (true=yes, false=no)
     * string  $on_new          (optional)  name of action (plugin-function) to activate in order to compute the event
     * string  $on_edit         (optional)  name of action (plugin-function) to activate in order to compute the event
     * string  $on_delete       (optional)  name of action (plugin-function) to activate in order to compute the event
     * string  $on_search       (optional)  name of action (plugin-function) to activate in order to compute the event
     * boolean $advanced_search (optional)  should advanced search form be shown (true=yes, false=no)
     * </pre>
     *
     * @access  public
     * @static
     * @param   array   $params
     * @param   Smarty  &$smarty
     * @return  string
     */
    function guiCreate($params, &$smarty)
    {
        global $YANA;

        /*
         * Parameters 'on_edit', 'on_delete', 'on_new', 'on_search'
         */
        settype($params['on_edit'],   "string");
        settype($params['on_delete'], "string");
        settype($params['on_new'],    "string");
        settype($params['on_search'], "string");
        $on_edit   = strtolower($params['on_edit']);
        $on_delete = strtolower($params['on_delete']);
        $on_new    = strtolower($params['on_new']);
        $on_search = strtolower($params['on_search']);
        $YANA->setVar('ON_EDIT',     $on_edit);
        $YANA->setVar('ON_DELETE',   $on_delete);
        $YANA->setVar('ON_NEW',      $on_new);
        $YANA->setVar('ON_SEARCH',   $on_search);
        /*
         * Parameter 'sort'
         */
        if (isset($_GET['sort'])) {
            $sort = $_GET['sort'];
        } else if (isset($_SESSION['sort'])) {
            $sort = $_SESSION['sort'];
        } else {
            $sort = $params['sort'];
        }
        settype($sort, "string");

        /*
         * Parameter 'where'
         */
        settype($params['where'], "string");
        $where = $params['where'];

        /*
         * Parameter 'template'
         */
        settype($params['template'], "string");
        $template = strtolower($params['template']);
        $YANA->setVar('NAMESPACE', $template);

        /*
         * Parameter 'file'
         */
        settype($params['file'], "string");
        $file = $params['file'];

        /*
         * Parameter 'table'
         */
        settype($params['table'], "string");
        $table = strtolower($params['table']);

        /*
         * Parameter 'titles'
         */
        if (isset($params['titles']) && $params['titles'] != 'hidden') {
            $show_titles = true;
        } else {
            $show_titles = false;
        }

        /*
         * Parameter 'desc'
         */
        if (isset($_GET['desc'])) {
            $desc = ($_GET['desc']) ? true : false;
        } else if (isset($_SESSION['desc'])) {
            $desc = $_SESSION['desc'];
        } else {
            $desc = $params['desc'];
        }
        settype($desc, "boolean");
        $_SESSION['desc'] = $desc;
        $YANA->setVar('DESC', $desc);

        /*
         * Parameter 'advanced_search'
         */
        if (isset($_GET['advanced_search'])) {
            $advanced_search = ($_GET['advanced_search']) ? true : false;
        } else if (isset($_SESSION['advanced_search'])) {
            $advanced_search = ($_SESSION['advanced_search']) ? true : false;
        } else {
            $advanced_search = $params['advanced_search'];
        }
        settype($advanced_search, "boolean");
        $_SESSION['advanced_search'] = $advanced_search;
        $YANA->setVar('ADVANCED_SEARCH', $advanced_search);

        /*
         * Parameter 'page'
         */
        if (isset($_GET['page'])) {
            $page = $_GET['page'];
        } else if (isset($_SESSION['page'])) {
            $page = $_SESSION['page'];
        } else {
            $page = $params['page'];
        }
        settype($page, "integer");
        if ($page < 0) {
            $page = 0;
        }
        $_SESSION['page'] = $page;
        $YANA->setVar('PAGE',       $page);
        $YANA->setVar('FIRST_PAGE', $page+1);

        /*
         * Parameter 'entries'
         */
        if (isset($_GET['entries'])) {
            $entries = $_GET['entries'];
        } else if (isset($_SESSION['entries'])) {
            $entries = $_SESSION['entries'];
        } else {
            $entries = $params['entries'];
        }
        settype($entries, "integer");
        if ($entries < 1) {
            $entries = 5;
        }
        $_SESSION['entries'] = $entries;
        $YANA->setVar('ENTRIES', $entries);

        /*
         * Begin business logic
         */
        $document = new smartTemplate();
        $primary_key = "";
        $document->insertByReference('PRIMARY_KEY',       $primary_key);
        $document->insertByReference('TABLE',             $table);
        $document->insertByReference('SHOW_FIELD_TITLES', $show_titles);

        $db = $YANA->connect($file);
        $db->read();
    
        if ($db->exists()) {
            $last_page = $db->length($table);
            $YANA->setVar('LAST_PAGE', $last_page);
            $primary_key = $db->structure->getPrimaryKey($table);

            /*
             * Parameter 'sort' 
             */
            if (empty($sort)) {
                $sort = $primary_key;
            }
            $_SESSION['sort'] = $sort;
            $YANA->setVar('SORT', $sort);

            $content =& $db->structure->get("TABLES.${table}.CONTENT");
            $document->insertByReference('CONTENT', $content);
    
            $liste = array();
            if ($last_page > ($entries*2)) {
                $dots = false;
                for($k=0;$k<ceil($last_page/$entries);$k++)
                {
                    $it   = count($liste);
                    $first = ($k*$entries);
                    $last  = ((($k+1)*$entries < $last_page) ? ($k+1)*$entries : $last_page);
                    if ($last_page > 10 * $entries && $k > 1 && $k < ceil($last_page/$entries) - 2) {
                        if (!$dots) {
                            $dots = true;
                            $liste .= '&nbsp;... ' . "\n";
                        }
                    } else {
                        $liste[$it]['FIRST'] = ($first+1);
                        $liste[$it]['LAST']  = $last;
                    }
                }
            }
            $document->insertByReference('LIST_OF_ENTRIES', $liste);
    
            switch ($template) {

                case 'view_seperated':
                    $document->setFilename($YANA->skin->getFile("gui_view_seperated"));
                    $document->insert('ROWS', $db->get($table, $where, (($sort)? "ORDER BY ".$sort : '').(($desc)? ' DESC' : ''),$page,$entries));
                    $result = $document->get();
                break;
    
                case 'view':
                    $document->setFilename($YANA->skin->getFile("gui_view"));
                    $document->insert('ROWS', $db->get($table, $where, (($sort)? "ORDER BY ".$sort : '').(($desc)? ' DESC' : ''),$page,$entries));
                    $result = $document->get();
                break;
    
                case 'new':
                    $document->setFilename($YANA->skin->getFile("gui_new"));
                    $result = $document->get();
                break;

                case 'edit':                      
                    $document->setFilename($YANA->skin->getFile("gui_edit"));
                    $ROWS = $db->get($table, $where, (($sort)? "ORDER BY ".$sort : '').(($desc)? ' DESC' : ''),$page,$entries);
                    $CURRENT_INDEX = array_pop(array_keys($ROWS));
                    if (!empty($where)) {
                        assert('!isset($temp);');
                        $temp = $db->get("$table.*.$primary_key", '', (($sort)? "ORDER BY ".$sort : '').(($desc)? ' DESC' : ''));
                        $temp = array_search($CURRENT_INDEX, $temp);
                        assert('is_int($temp);');
                        $_SESSION['page'] = $temp;
                        $YANA->setVar('PAGE', $temp);
                        unset($temp);
                    }
                    $document->insert('ROWS', $ROWS);
                    $document->insert('CURRENT_INDEX', $CURRENT_INDEX);
                    $result = $document->get();
                break;

                case 'search':
                    if ($advanced_search) {
                        $document->insert('HITLIST_TEMPLATE', ($YANA->skin->getFile("gui_view")));
                        $document->setFilename($YANA->skin->getFile("gui_search"));
                    } else {
                        $document->insert('HITLIST_TEMPLATE', ($YANA->skin->getFile("gui_view")));
                        $document->setFilename($YANA->skin->getFile("gui_small_search"));
                    }
                    $where = '';
                    foreach (array_keys($content) as $fieldname)
                    {
                        if ((!$advanced_search || $_POST[strtolower('is_active_'.$fieldname)] === 'true') && !empty($_POST[strtoupper($fieldname)])) {
                            if (!empty($where)) {
                                $where .= ', ';
                            }
                            $where .= $fieldname.'='.$_POST[strtoupper($fieldname)];
                        }
                    }                
                    $document->insert('IS_SEARCH', true);
                    $document->insert('ROWS', $db->get($table, $where, (($sort)? "ORDER BY ".$sort : '').(($desc)? ' DESC' : ''),$page,$entries));
                    $result = $document->get();
                break;

                default:
                    trigger_error("Template-Syntaxerror, unknown template for GUI-Generator: \"".$template."\"", E_USER_WARNING);
                break;
            }
        } else {
            trigger_error("Template-Syntaxerror, database connection failed", E_USER_WARNING);
            $result = "";
        }
    
        return $result;
    
    }

    /** 
     * «smarty processor» htmlPostProcessor
     *
     * @access  public
     * @static
     * @param   array   $params
     * @param   Smarty  &$smarty
     * @return  string
     */
    function htmlPostProcessor($source, &$smarty)
    {
        if (!is_string($source)) {
            return $source;
        }
        global $lcn_note, $instance_id, $YANA;

        $permission = $YANA->getVar('PERMISSION');

        /* Create field for internal form validation */
        if (!is_int($permission) || $permission < 1) {
            $source = str_replace("</form>", "<span class=\"yana_button\"><input type=\"text\" name=\"yana_url\"></span>\n</form>", $source);
        }

        /* Instance Management */
        if (isset($YANA))  {
            $licence = $YANA->getVar("LICENCE.KEY");
            if (!empty($licence)) {
                $a = $YANA->getVar("LICENCE");
                $lcn_note = Layout::fillTemplate($lcn_note, $a);
                $source = preg_replace("/<\/body>/i", $lcn_note."</body>", $source);
            } else {
                $source = preg_replace("/<\/body>/i", $instance_id."</body>", $source);
            }
        } else {
            $source = preg_replace("/<\/body>/i", $instance_id."</body>", $source);
        }

        return $source;
    }

    /**
     * «smarty processor» processLanguageInstructions
     *
     * @access  public
     * @static
     * @param   array   $params
     * @param   Smarty  &$smarty
     * @return  string
     */
    function processLanguageInstructions($source, &$smarty)
    {
        $source = preg_replace("/".DisplayUtility::_regExpToken("(\\\$LANGUAGE\..*)")."/Us", YANA_LEFT_DELIMITER."\\1|embeddedTags".YANA_RIGHT_DELIMITER, $source);
        return $source;
    }
    
    /**
     * «smarty processor» htmlPreProcessor
     *
     * @access public
     * @static
     * @param string $source
     * @param smarty &$templateClass
     * @return string
     */
    function htmlPreProcessor($source, &$templateClass)
    {
        if (!is_string($source)) {
            return $source;
        }
        global $YANA;

        /* funcionality of 'include' function has been moved to 'import', so ignore the original */
        $source = preg_replace("/".DisplayUtility::_regExpToken("include .*")."/Usi", "", $source);
        /* deactivate 'include_php' for security reasons */
        $source = preg_replace("/".DisplayUtility::_regExpToken("include_php .*")."/Usi", "", $source);
        /* deactivate 'php' for security reasons */
        $source = preg_replace("/".DisplayUtility::_regExpToken("php").".*".DisplayUtility::_regExpToken("\/php")."/Usi", "", $source);
        /* reformat abbreviated %FOO% tags to [%$FOO%] */
        $source = preg_replace("/".toRegExp(YANA_UNI_DELIMITER)."(([A-Z]|_|-|\.)+)".toRegExp(YANA_UNI_DELIMITER)."/", DisplayUtility::_varToken("\\1"), $source);

        $basedir = $templateClass->get_template_vars('BASEDIR');
        settype($basedir, "string");
        $is_include = $templateClass->get_template_vars('FILE_IS_INCLUDE');
        if ($is_include) {
            $source = preg_replace("/^.*<body(.*)>(.*)<\/body>.*$/Usi", "<div\\1>\\2</div>", $source);
        }
    
        if (!empty($basedir)) {
            preg_match_all('/('.DisplayUtility::_regExpToken(')import\s+(?:preparser\s+|)file="(\S*)(".*').')/Ui', $source, $match2);
            for ($i=0;$i<count($match2[0]);$i++)
            {
                if (preg_match('/\sliteral\s/i' ,$match2[0][$i])) {
                    $source = preg_replace('/'.toRegExp($match2[0][$i]).'/i', preg_replace("/\sliteral\s/i", " ", $match2[0][$i]), $source);
                } else if (preg_match('/\spreparser\s/i' ,$match2[0][$i])) {
                    $source = preg_replace('/'.toRegExp($match2[0][$i]).'/i', preg_replace("/.*<body[^>]*>(.*)<\/body>.*/si", "\\1", implode("", file($basedir.$match2[2][$i]))), $source);
                } else {
                    $source = str_replace($match2[0][$i], $match2[1][$i].'import file="'.$basedir.$match2[2][$i].$match2[3][$i], $source);
                }
            }

            preg_match_all('/('.DisplayUtility::_regExpToken(')insert\s+file="(\S*)(".*').')/Ui', $source, $match2);
            for ($i=0;$i<count($match2[0]);$i++)
            {
                    $source = preg_replace('/'.toRegExp($match2[0][$i]).'/i', $match2[1][$i].'insert file="'.$basedir.$match2[2][$i].$match2[3][$i], $source);
            }
    
            preg_match_all('/ background\s*=\s*"(\S*)"/i', $source, $match2);
            for ($i=0;$i<count($match2[1]);$i++)
            {
                if (!preg_match('/^https?:\/\/\S*/i', $match2[1][$i]) && !preg_match('/^'.DisplayUtility::_regExpVarToken('PHP_SELF').'/i', $match2[1][$i])) {
                    $source = preg_replace('/ background\s*=\s*"'.toRegExp($match2[1][$i]).'"/i', ' background="'.$basedir.$match2[1][$i].'"', $source);
                }
            }
            preg_match_all('/ src\s*=\s*"(\S*)"/i', $source, $match2);
            for ($i=0;$i<count($match2[1]);$i++)
            {
                if (!preg_match('/ src\s?=\s?"\S*"/i', $match2[1][$i]) && !preg_match('/^https?:\/\/\S*/i', $match2[1][$i]) && !preg_match('/^'.DisplayUtility::_regExpVarToken('PHP_SELF').'/i', $match2[1][$i])) {
                    $source = preg_replace('/ src\s*=\s*"'.toRegExp($match2[1][$i]).'"/i', ' src="'.$basedir.$match2[1][$i].'"', $source);
                }
            }
            preg_match_all("/\.src\s*=\s*'(\S*)'/i", $source, $match2);
            for ($i=0;$i<count($match2[1]);$i++)
            {
                if (!preg_match("/\.src\s*=\s*'\S*'/i", $match2[1][$i]) && !preg_match('/^https?:\/\/\S*/i', $match2[1][$i]) && !preg_match('/^'.DisplayUtility::_regExpVarToken('PHP_SELF').'/i', $match2[1][$i])) {
                    $source = preg_replace("/\.src\s?=\s?'".toRegExp($match2[1][$i])."'/i", ".src='".$basedir.$match2[1][$i]."'", $source);
                }
            }
            preg_match_all("/ url\(\"([^\"]*)\"\)/i", $source, $match2);
            for ($i=0;$i<count($match2[1]);$i++)
            {
                if (!preg_match("/ url\(\"[^\"]*\"\)/i", $match2[1][$i]) && !preg_match('/^https?:\/\/\S*/i', $match2[1][$i]) && !preg_match('/^'.DisplayUtility::_regExpVarToken('PHP_SELF').'/i', $match2[1][$i])) {
                    $source = preg_replace("/ url\(\"".toRegExp($match2[1][$i])."\"\)/i", " url(\"".$basedir.$match2[1][$i]."\")", $source);
                }
            }
            preg_match_all("/ url\('([^']*)'\)/i", $source, $match2);
            for ($i=0;$i<count($match2[1]);$i++)
            {
                if (!preg_match("/ url\('[^']*'\)/i", $match2[1][$i]) && !preg_match('/^https?:\/\/\S*/i', $match2[1][$i]) && !preg_match('/^'.DisplayUtility::_regExpVarToken('PHP_SELF').'/i', $match2[1][$i])) {
                    $source = preg_replace("/ url\('".toRegExp($match2[1][$i])."'\)/i", " url('".$basedir.$match2[1][$i]."')", $source);
                }
            }
            preg_match_all('/ href\s*=\s*"([^"]*)"/i', $source, $match2);
            for ($i=0;$i<count($match2[1]);$i++)
            {
                if (!preg_match('/ href\s*=\s*"[^"]*"/i', $match2[1][$i]) && !preg_match('/^javascript:/i', $match2[1][$i]) && !preg_match('/^\&\#109\;\&\#97\;\&\#105\;\&\#108\;\&\#116\;\&\#111\;\&\#58\;\S*/i', $match2[1][$i]) && !preg_match('/^mailto:\S*/i', $match2[1][$i]) && !preg_match('/^https?:\/\/\S*/i', $match2[1][$i]) && !preg_match('/^'.DisplayUtility::_regExpVarToken('PHP_SELF').'/i', $match2[1][$i])) {
                    $source = preg_replace('/ href\s?=\s?"'.toRegExp($match2[1][$i]).'"/i', ' href="'.$basedir.$match2[1][$i].'"', $source);
                }
            }

        }
    
        return DisplayUtility::scanForAt($source);
    }

    /**
     * «smarty outputfilter» outputfilter
     *
     * @access  public
     * @static
     * @param   string  $source
     * @param   Smarty  &$templateClass
     * @return  string
     */
    function outputFilter($source, &$templateClass)
    {
        /* Create form id */
        global $YANA;       
        if ($YANA->getVar('DISABLE_FORM_ID') !== true) {
            $yana_form_id = md5(uniqid(rand(), true));
            if (strpos($source, "</form>") !== false) {
                $source   = str_replace("</form>", "<span class=\"yana_button\"><input type=\"text\" name=\"yana_form_id\" value=\"$yana_form_id\"></span>\n</form>", $source);
                $_SESSION['yana_form_id'] = $yana_form_id;
                $YANA->setVar('DISABLE_FORM_ID', true);
            }
        }

        $basedir = $templateClass->get_template_vars('BASEDIR');
        /* import stylesheets */
        $style_list = $templateClass->get_template_vars('SYSTEM_STYLE');
        assert('is_null($style_list) || is_array($style_list);');
        if (is_array($style_list) && count($style_list) > 0) {
            foreach ($style_list as $stylesheet)
            {
                $source = preg_replace('/^(\s*<\/head>)/m', '        '.DisplayUtility::css($stylesheet)."\n".'${1}', $source);
            }
        }

        /* import javascripts */
        $script_list = $templateClass->get_template_vars('SYSTEM_SCRIPT');

        assert('is_null($script_list) || is_array($script_list);');
        if (is_array($script_list) && count($script_list) > 0) {
            foreach ($script_list as $script)
            {
                $source = preg_replace('/^(\s*<\/head>)/m', '        '.DisplayUtility::script($script)."\n".'${1}', $source);
            }
        }
        return $source;
    }

    /**
     * «smarty modifier» date
     *
     * @access  public
     * @static
     * @param   string  $time
     * @return  string
     */
    function date($time)
    {
        settype($time, "integer");
        global $YANA;
    
        if (empty($time)) {
            $time = time();
        }

        return '<script type="text/javascript" language="JavaScript">date=new Date('.$time."000); document.write(".$YANA->getVar("DATE.".$YANA->getVar("PROFILE.TIMEFORMAT")).");</script>";

    }

    /**
     * «smarty modifier» entities
     *
     * @access  public
     * @static
     * @param   string  $time
     * @return  string
     */
    function entities($string)
    {
        return htmlentities($string);
    }

    /**
     * «smarty modifier» url
     *
     * @access  public
     * @static
     * @param   string  $time
     * @return  string
     */
    function url($string) {

        settype($string, "string");
        global $YANA;
    
        preg_match_all("/(&|^)(.*)=(.*)(&|$)/U", $string, $m);
        for ($i=0;$i<count($m[0]);$i++) 
        {
            $string = preg_replace("/".toRegExp($m[0][$i])."/", $m[1][$i].urlencode($m[2][$i])."=".urlencode($m[3][$i]).$m[4][$i], $string);
        }

        return $YANA->getVar('PHP_SELF')."?".((@session_id() != "") ? @session_name()."=".@session_id() : "")."&amp;id=".$YANA->getVar('ID')."&amp;".htmlentities($string);

    }

    /**
     * «smarty modifier» href
     *
     * @access  public
     * @static
     * @param   string  $time
     * @return  string
     */
    function href($string) {

        return '"'.DisplayUtility::url($string).'"';

    }

    /**
     * «smarty modifier» css
     *
     * @access  public
     * @static
     * @param   string  $time
     * @return  string
     */
    function css($string)
    {
        settype($string, "string");
        if (!preg_match("/^[\w-_\.\/]+\.css$/si", $string)) {
            return "";
        } else {
            return '<link rel="stylesheet" type="text/css" href="'.$string.'">';
        }
    }

    /**
     * «smarty modifier» script
     *
     * @access  public
     * @static
     * @param   string  $time
     * @return  string
     */
    function script($string)
    {
        settype($string, "string");
        if (!preg_match("/^[\w-_\.\/]+\.js$/si", $string)) {
            return "";
        } else {
            return '<script type="text/javascript" language="javascript" src="'.$string.'"></script>';
        }
    }

    /**
     * «smarty modifier» embeddedTags
     *
     * @access  public
     * @static
     * @param   string  $source
     * @param   bool    $use_html_entities
     * @return  string
     */
    function embeddedTags($txt, $use_html_entities = true)
    {
        if (!is_string($txt)) {
            return $txt;
        }
        
        if (!is_bool($use_html_entities)) {
            trigger_error("Wrong argument type for argument 2 in function embeddedTags(). Boolean expected, found '".gettype($input)."' instead.", E_USER_ERROR);
            return $txt;
        }

        /* if not necessary -> skip the whole section for better performance */
        if (is_int(strpos($txt, '['))) {

            $invalid_resource = '<img title="the resource %RESOURCE% was blocked because it contained illegal characters" alt="invalid %RESOURCE%" border="0" src="%DATADIR%icon_x.gif">';

            $txt = preg_replace("/\[php\](.*)(\[\/php\]|$)/Usi", "[code]<?php\n\\1\n?>[/code]", $txt);
            while (preg_match('/\[code\](.*)(\[\/code\]|$)/Us', $txt, $m))
            {
                $m[1] = preg_replace("/\[\/?(b|i|emp|h|code|php|img|mark|color|url|mail)\]/si", "", $m[1]);
                /* This is to avoid double quoting , since highlight_string() will quote the string again. */
                $m[1] = html_entity_decode($m[1]);
                $m[1] = '<code style="white-space: pre-wrap">'.highlight_string($m[1],true).'</code>';
                $txt  = str_replace($m[0], $m[1], $txt);
            }
            unset($m);
            $txt = preg_replace("/\[b\](.*)(\[\/b\]|$)/Us",               "<span style=\"font-weight: bold;\">\\1</span>", $txt);
            $txt = preg_replace("/\[i\](.*)(\[\/i\]|$)/Us",               "<span style=\"font-style: italic;\">\\1</span>", $txt);
            $txt = preg_replace("/\[u\](.*)(\[\/u\]|$)/Us",               "<span style=\"text-decoration: underline;\">\\1</span>", $txt);
            $txt = preg_replace("/\[emp\](.*)(\[\/emp\]|$)/Us",           "<span class=\"EMPHASIZE\">\\1</span>", $txt);
            $txt = preg_replace("/\[h\](.*)(\[\/h\]|$)/Us",               "<p class=\"HIGHLIGHT\">\\1</p>", $txt);
            $txt = preg_replace("/\[c\](.*)(\[\/c\]|$)/Us",               "<div class=\"KOMMENTAR\">\\1</div>", $txt);
            $txt = preg_replace("/\[hide\](.*)(\[\/hide\]|$)/Us",         "<div style=\"padding: 5px; border: 1px solid #555555; background-color: #CCCCCC; color: #CCCCCC\" onMouseOver=\"this.style.backgroundColor='#F0F0F0'; this.style.color='#333333'\" onMouseOut=\"this.style.backgroundColor='#CCCCCC'; this.style.color='#CCCCCC'\">\\1</div>", $txt);

            $txt = preg_replace("/\[small\](.*)(\[\/small\]|$)/Us",       "<span style=\"font-size: x-small\">\\1</span>", $txt);
            $txt = preg_replace("/\[big\](.*)(\[\/big\]|$)/Us",           "<span style=\"font-size: large\">\\1</span>", $txt);
            $txt = preg_replace("/\[mark\](.*)(\[\/mark\]|$)/Usi",         "<span style=\"background-color:#FFFF00\">\\1</span>", $txt);
            $txt = preg_replace("/\[mark=(\w+|\#[\da-fA-F]{3}|\#[\da-fA-F]{6})\](.*)(\[\/mark\]|$)/Us", '<span style="background-color:${1}">${2}</span>', $txt);
            $txt = preg_replace("/\[color\](.*)(\[\/color\]|$)/Us",       "<span style=\"color:#000000\">\\1</span>", $txt);
            $txt = preg_replace("/\[color=(\w+|\#[\da-fA-F]{3}|\#[\da-fA-F]{6})\](.*)(\[\/color\]|$)/Us", '<span style="color:${1}">${2}</span>', $txt);

            $txt = preg_replace("/\[mail=mailto:(.*)\]/Us",               "[mail=\\1]", $txt);
            $txt = preg_replace("/\[mail]mailto:(.*)\[\/mail\]/Us",       "[mail]\\1[/mail]", $txt);

            /* images */
            $matches = array();
            while (preg_match("/\[img\](.*)\[\/img\]/U", $txt, $matches))
            {
                if (preg_match("/^[\w\d-_\/]+\.(png|jpg|gif|jpeg)$/i", $matches[1], $ext)) {
                    $txt = str_replace($matches[0], '<img alt="" border="0" src="'.htmlentities(strip_tags(preg_replace("/\[wbr\]/i", "", $matches[1]))).'" style="max-width: 320px; max-height: 240px" onload="javascript:if(this.width>320) { this.width=320; }; if(this.height>240) { this.height=240; };">', $txt);
                } else {
                    $txt = str_replace($matches[0], str_replace('%RESOURCE%', 'image', $invalid_resource), $txt);
                }
            }
            $matches = array();

            /* mail */
            /* may contain word-/line- breaks that need to be removed */
            while (preg_match('/\[mail=[^\[\]]*\[wbr\]/i', $txt))
            {
                $txt   = preg_replace('/(\[mail=[^\[\]]*)\[wbr\]/i', '${1}', $txt);
            }
            unset($count);
            while (preg_match("/\[mail=(.*)\](.*)\[\/mail\]/Usi", $txt, $matches1) || preg_match("/\[mail\](.*)\[\/mail\]/Ui", $txt, $matches2))
            {
                if (!empty($matches1)) {
                    $mail_match =& $matches1[0];
                    $mail_href  =  $matches1[1];
                    $mail_text  =  $matches1[2];
                } else if (!empty($matches2)) {
                    $mail_match =& $matches2[0];
                    $mail_href  =  $matches2[1];
                    $mail_text  =  $matches2[1];
                    $mail_text  =  preg_replace('/ ?(\[wbr\]|\[br\])/','',$mail_text);
                    if (strlen($mail_text) > 40) {
                        $mail_text = substr($mail_text,0,34) . "..." . substr($mail_text,-3);
                    }
                }
                /* Count in the possibility of some nasty guy injecting white space characters */
                $mail_href = preg_replace('/[\x00-\x1f]/','',$mail_href);
                /* Although there should not be any tags - you never know ... */
                $mail_href = strip_tags($mail_href);
                $mail_href = preg_replace('/ ?(\[wbr\]|\[br\])/','',$mail_href);
                $mail_href = preg_replace('/^mailto:/i', '', $mail_href);
                $mail_href = untaintInput($mail_href, 'mail');
                $mail_href = htmlentities($mail_href);
                if (!empty($mail_href)) {
                    $txt = str_replace($mail_match, '<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;'.$mail_href.'" target="_blank">'.$mail_text.'</a>', $txt);
                } else {
                    $txt = str_replace($mail_match, str_replace('%RESOURCE%', 'mail', $invalid_resource), $txt);
                }
            }
            $matches1 = array();
            $matches2 = array();

            /* url */
            /* may contain word-/line- breaks that need to be removed */
            while (preg_match('/\[url=[^\[\]]*(?:\[wbr\]|\[br\])/si', $txt))
            {
                $txt   = preg_replace('/(\[url=[^\[\]]*)(?:\[wbr\]|\[br\])/si', '${1}', $txt);
            }
            unset($count);
            while (preg_match("/\[url=(.*)\](.*)\[\/url\]/Usi", $txt, $matches1) || preg_match("/\[url\](.*)\[\/url\]/Ui", $txt, $matches2))
            {
                if (!empty($matches1)) {
                    $uri_match =& $matches1[0];
                    $uri_href  =  $matches1[1];
                    $uri_text  =  $matches1[2];
                } else if (!empty($matches2)) {
                    $uri_match =& $matches2[0];
                    $uri_href  =  $matches2[1];
                    $uri_text  =  $matches2[1];
                    $uri_text  =  preg_replace('/ ?(\[wbr\])/','',$uri_text);
                    if (strlen($uri_text) > 40) {
                        $uri_text = substr($uri_text,0,34) . "..." . substr($uri_text,-3);
                    }
                }
                /* Count in the possibility of some nasty guy injecting white space characters */
                $uri_href = preg_replace('/[\x00-\x1f]/','',$uri_href);
                /* Although there should not be any tags - you never know ... */
                $uri_href = strip_tags($uri_href);
                $uri_href = preg_replace('/ ?(\[wbr\]|\[br\])/','',$uri_href);
                $uri_href = untaintInput($uri_href, 'url');
                $uri_href = htmlentities($uri_href);
                if (!preg_match('/^(https?:\/\/|ftp:\/\/)/', $uri_href) && preg_match('/^[^:]+:/', $uri_href)) {
                    $uri_href = '';
                } else if (!preg_match('/^[^:]+:/', $uri_href)) {
                    $uri_href = 'http://'.$uri_href;
                }
                if (!empty($uri_href)) {
                    $txt = str_replace($uri_match, '<a href="'.$uri_href.'" target="_blank">'.$uri_text.'</a>', $txt);
                } else {
                    $txt = str_replace($uri_match, str_replace('%RESOURCE%', 'uri', $invalid_resource), $txt);
                }
                unset($uri_match);
                unset($uri_href);
                unset($uri_text);
            }
            $matches1 = array();
            $matches2 = array();

            /* line break */
            $txt = str_replace('[br]', '<br>', $txt);

            /* word break */
            $txt = str_replace('[wbr]', '<span style="font-size: 0px"> </span>', $txt);

            /* remove uncaught tags */
            $txt = preg_replace("/\[\/?(b|i|emp|h|code|php|img|mark|color|url|mail)\]/si", "", $txt);
        }

        assert('is_string($txt);');
        return $txt;
    }

    /**
     * «smarty modifier» scanForAt
     *
     * @access  public
     * @static
     * @param   string  $source
     * @return  string
     */
    function scanForAt($source)
    {
    
        if (!is_string($source)) {
            return $source;
        } else {
            preg_match_all("/[\w\.\-_]+@[\w\.\-_]+/", $source, $matches);
    
            for ($i=0; $i<count($matches[0]); $i++)
            {
                $source = str_replace($matches[0][$i], String_type::htmlEntities($matches[0][$i]), $source);
            }
    
            return $source;
        }
    
    }

    /**
     * «smarty modifier» smilies
     *
     * @access  public
     * @static
     * @param   string  $txt
     * @return  string
     */
    function smilies($txt)
    {
        assert('is_string($txt);');
        if (!is_string($txt)) {
            return $txt;
        }
    
        global $YANA;
        if (isset($YANA)) {
            $smilies = $YANA->getVar('SMILIES');
            $smilies_dir = $YANA->getVar('PROFILE.SMILEYDIR');
        } else {
            global $smilies, $smilies_dir;
        }
    
        /* default smilies */
        if (isset($smilies) && is_array($smilies)) {
            if (in_array("smile", $smilies))        { 
                $txt = preg_replace("/:[\-oO]?\)/", '<img alt=":-)" border="0" hspace="2" src="'.$smilies_dir.'smile.gif">', $txt);
            }
            if (in_array("teufelchen", $smilies))   {
                $txt = preg_replace("/>:[\-oO]?\)/", '<img alt="&gt-)" border="0" hspace="2" src="'.$smilies_dir.'teufelchen.gif">', $txt);
            }
            if (in_array("boese", $smilies))        {
                $txt = preg_replace("/:[\-oO]?\(/", '<img alt=":-(" border="0" hspace="2" src="'.$smilies_dir.'boese.gif">', $txt);
            }
            if (in_array("keinemeinung", $smilies)) {
                $txt = preg_replace("/:[\-oO]?\|/", '<img alt=":-|" border="0" hspace="2" src="'.$smilies_dir.'keinemeinung.gif">', $txt);
            }
            if (in_array("lachen", $smilies))       {
                $txt = preg_replace("/:[\-oO]?D/", '<img alt=":-D" border="0" hspace="2" src="'.$smilies_dir.'lachen.gif">', $txt);
            }
            if (in_array("grinsen", $smilies))      {
                $txt = preg_replace("/;[\-oO]?\)/", '<img alt=";-)" border="0" hspace="2" src="'.$smilies_dir.'grinsen.gif">', $txt);
            }
            if (in_array("zunge", $smilies))        {
                $txt = preg_replace("/:[\-oO]?P/", '<img alt=":-P" border="0" hspace="2" src="'.$smilies_dir.'zunge.gif">', $txt);
            }
            if (in_array("traurig", $smilies))      {
                $txt = preg_replace("/:[\'\*]\(/", '<img alt=":*(" border="0" hspace="2" src="'.$smilies_dir.'traurig.gif">', $txt);
            }
        }
    
        /* if not necessary -> skip the whole section for better performance */
        if (is_int(strpos($txt, ':'))) {
            /* Emot-Codes */
            for ($j=0;$j<count($smilies);$j++)
            {
                while (preg_match("/:".$smilies[$j].":(\s|\[wbr\]|\[br\]|<br \/>)*:".$smilies[$j].":/i", $txt)) 
                {
                    $txt = preg_replace("/:".$smilies[$j].":(\s|\[wbr\]|\[br\]|<br \/>)*:".$smilies[$j].":/i", ':'.$smilies[$j].':', $txt);
                }
                $txt = preg_replace("/:".addcslashes($smilies[$j], "+()[]{}.?*/\\$^").":/", '<img alt="" border="0" hspace="2" src="'.$smilies_dir.$smilies[$j].'.gif">', $txt);
            }
        }
    
        assert('is_string($txt);');
        return $txt;
    }

    /**
     * «smarty function» guiSmilies
     *
     * @static
     * @access  public
     * @name    displayutility::guismilies()
     * @param   string $time
     * @param   smarty &$smarty
     * @return  string
     *
     * @see     displayutility::loadsmilies()
     */
    function guiSmilies($params, &$smarty)
    {
        global $YANA;
        $TABLE_smilies = '<table summary="smilies" class="gui_generator_smilies"><tr>';
        $title_smilies = $YANA->getVar("LANGUAGE.TITLE_SMILIES");
        $smileyDir     = $YANA->getVar("PROFILE.SMILEYDIR");
        $smilies       = $YANA->getVar("SMILIES");
        settype($params['width'], "integer");
        if ($params['width'] < 1) {
            $params['width'] = 1; 
        }

        for ($j=0;$j<count($smilies);$j++)
        {
            if ($j % $params['width'] == 0 && $j > 0) { 
                $TABLE_smilies .= '</tr><tr>';
            }
            $TABLE_smilies .= '<td><a title="'.$title_smilies.'" href="javascript://:'.urlencode($smilies[$j]).':"><img alt="'.$smilies[$j].'" src="'.$smileyDir.$smilies[$j].'.gif" onmousedown="addIcon(\':'.$smilies[$j].':\',\''.$params['target'].'\',event)"></a></td>'."\n";
        }
    
        return $TABLE_smilies."</tr></table>";
    }

    /**
     * loadSmilies
     *
     * @static
     * @access  public
     * @name    displayutility::loadsmilies()
     * @param   string  $user_dir (optional)
     *
     * @see     displayutility::guismilies()
     */
    function loadSmilies($user_dir="./")
    {
        assert('is_string($user_dir);');
        assert('is_dir($user_dir);');
        settype($user_dir, "string");
    
        global $YANA;
        if (isset($YANA)) {
            $smilies_dir = $YANA->getVar('PROFILE.SMILEYDIR');
        } else {
            global $smilies, $smilies_dir;
            $smilies_dir = $user_dir;
        }
    
        if (is_dir($smilies_dir) && (empty($smilies) || is_null($smilies))) {
            $smilies = array();
    
            $dir = dir($smilies_dir);
            while ($txt = $dir -> read()) 
            {
                if (preg_match("/\.gif$/i", $txt)) {
                    $smilies[count($smilies)] = substr($txt, 0, strrpos($txt, "."));
                }
            }
            $dir->close();
            sort($smilies);
        }
    
        if (isset($YANA)) {
            $YANA->setVar('SMILIES', $smilies);
        }
    
    }

    /**
     * «smarty function» guiImport
     *
     * @static
     * @access  public
     * @param   string  $time
     * @param   smarty  &$smarty
     * @return  string
     */
    function guiImport($param, &$smarty)
    {
        $t = new smartTemplate($param['file']);
        unset($param['file']);
        if (count($param)>0) {
            $t->insertByReference('*',$param);
        }
        $t->insert('FILE_IS_INCLUDE', "true");
        $include = $t->get();
        return $include;
    }

    /**
     * create a token with quoted delimiters
     *
     * @static
     * @access  private
     * @param   string  $input
     * @return  string
     */
    function _regExpToken($input)
    {
        assert('is_string($input);');
        settype($input, "string");
        return preg_quote(YANA_LEFT_DELIMITER).$input.preg_quote(YANA_RIGHT_DELIMITER);
    }

    /**
     * create a token refering to a variable with quoted delimiters
     *
     * @static
     * @access  private
     * @param   string  $input
     * @return  string
     */
    function _regExpVarToken($input)
    {
        assert('is_string($input);');
        settype($input, "string");
        return preg_quote(YANA_LEFT_DELIMITER).'\$'.strtoupper($input).preg_quote(YANA_RIGHT_DELIMITER);
    }
    
    /**
     * create a token refering to a variable
     *
     * @static
     * @access  private
     * @param   string  $input
     * @return  string
     */
    function _varToken($input)
    {
        assert('is_string($input);');
        settype($input, "string");
        return YANA_LEFT_DELIMITER.'$'.strtoupper($input).YANA_RIGHT_DELIMITER;
    }
    
    /**
     * create a token
     *
     * @static
     * @access  private
     * @param   string  $input
     * @return  string
     */
    function _token($input)
    {
        assert('is_string($input);');
        settype($input, "string");
        return YANA_LEFT_DELIMITER.strtoupper($input).YANA_RIGHT_DELIMITER;
    }

}
?>