Example #1
0
/**
 * Builds expression html tree
 *
 * @param array $expressionTree output of getExpressionTree() function
 * @param array $next           parameter only for recursive call; should be empty array
 * @param int $letterNum        parameter only for recursive call; should be 0
 * @param int $level            parameter only for recursive call
 * @param string $operand       parameter only for recursive call
 *
 * @return bool                 returns true if element is found, false - otherwise
 */
function buildExpressionHtmlTree(array $expressionTree, array &$next, &$letterNum, $level = 0, $operand = null)
{
    $treeList = array();
    $outline = '';
    end($expressionTree);
    $lastKey = key($expressionTree);
    foreach ($expressionTree as $key => $element) {
        switch ($element['type']) {
            case 'operand':
                $next[$level] = $key != $lastKey;
                $expr = expressionLevelDraw($next, $level);
                $expr[] = SPACE;
                $expr[] = italic($element['operand'] == '&' ? _('AND') : _('OR'));
                $levelDetails = array('list' => $expr, 'id' => $element['id'], 'expression' => array('value' => $element['expression']));
                $levelErrors = expressionHighLevelErrors($element['expression']);
                if (count($levelErrors) > 0) {
                    $levelDetails['expression']['levelErrors'] = $levelErrors;
                }
                $treeList[] = $levelDetails;
                list($subOutline, $subTreeList) = buildExpressionHtmlTree($element['elements'], $next, $letterNum, $level + 1, $element['operand']);
                $treeList = array_merge($treeList, $subTreeList);
                $outline .= $level == 0 ? $subOutline : '(' . $subOutline . ')';
                if ($operand !== null && $next[$level]) {
                    $outline .= ' ' . $operand . ' ';
                }
                break;
            case 'expression':
                $next[$level] = $key != $lastKey;
                $letter = num2letter($letterNum++);
                $outline .= $letter;
                if ($operand !== null && $next[$level]) {
                    $outline .= ' ' . $operand . ' ';
                }
                if (defined('NO_LINK_IN_TESTING')) {
                    $url = new CSpan($element['expression']);
                } else {
                    $expressionId = 'expr_' . $element['id'];
                    $url = new CSpan($element['expression'], 'link');
                    $url->setAttribute('id', $expressionId);
                    $url->setAttribute('onclick', 'javascript: copy_expression("' . $expressionId . '");');
                }
                $expr = expressionLevelDraw($next, $level);
                $expr[] = SPACE;
                $expr[] = bold($letter);
                $expr[] = SPACE;
                $expr[] = $url;
                $levelDetails = array('list' => $expr, 'id' => $element['id'], 'expression' => array('value' => $element['expression']));
                $levelErrors = expressionHighLevelErrors($element['expression']);
                if (count($levelErrors) > 0) {
                    $levelDetails['expression']['levelErrors'] = $levelErrors;
                }
                $treeList[] = $levelDetails;
                break;
        }
    }
    return array($outline, $treeList);
}
Example #2
0
/***************************************************************************
 *   nolink.php                                                            *
 *   Yggdrasil: Unidentified people mentioned in sources                   *
 *   (Part of the experimental source linkage                              *
 *                                                                         *
 *   Copyright (C) 2009-2011 by Leif B. Kristensen <*****@*****.**>   *
 *   All rights reserved. For terms of use, see LICENSE.txt                *
 ***************************************************************************/
require "./settings/settings.php";
require_once "./langs/{$language}.php";
require "./functions.php";
$title = 'Uidentifiserte personer';
require "./header.php";
echo "<div class=\"normal\">\n";
echo "<h2>Uidentifiserte personer fra lenking:</h2>\n";
$handle = pg_query("\n    SELECT\n        s.source_id AS source,\n        part_ldesc(s.part_type) AS s_type,\n        get_lsurety(l.surety_fk) AS surety,\n        get_lrole(l.role_fk) AS rolle,\n        l.s_name AS name,\n        get_source_text(s.source_id) AS txt,\n        link_expand(l.sl_note) AS note\n    FROM\n        sources s,\n        source_linkage l\n    WHERE\n        l.source_fk = s.source_id\n    AND\n        l.person_fk IS NULL\n    ORDER BY\n        s.source_date,\n        s.sort_order,\n        l.per_id\n");
echo "<ol>\n";
while ($row = pg_fetch_assoc($handle)) {
    $principal = fetch_val("\n        SELECT person_fk FROM source_linkage\n        WHERE source_fk = " . $row['source'] . " AND role_fk = 1\n    ");
    echo "<li>" . bold($row['name']) . '<br />' . $row['surety'] . ' ' . $row['rolle'] . ' ved ' . $row['s_type'];
    if ($principal) {
        echo ' av ' . linked_name($principal, './family.php');
    }
    echo '. ' . $row['txt'];
    echo conc(italic($row['note']));
    echo conc(paren(to_url('./source_manager.php', array('node' => $row['source']), 'Til kildebehandler')));
    echo "</li>\n";
}
echo "</ol>\n";
echo "</div>\n";
include "./footer.php";
Example #3
0
/**
 * Generates array with HTML items representing operation with description
 *
 * @param int $type short or long description, use const. SHORT_DESCRIPTION and LONG_DESCRIPTION
 * @param array $data
 * @param int $data['operationtype'] type of operation: OPERATION_TYPE_MESSAGE, OPERATION_TYPE_COMMAND, ...
 * @param int $data['opmessage']['mediatypeid'] type id of message media
 * @param bool $data['opmessage']['default_msg'] should default message be used
 * @param bool $data['opmessage']['operationid'] if true $data['operationid'] will be used to retrieve default messages from DB
 * @param string $data['opmessage']['subject'] subject of message
 * @param string $data['opmessage']['message'] message it self
 * @param array $data['opmessage_usr'] list of user ids if OPERATION_TYPE_MESSAGE
 * @param array $data['opmessage_grp'] list of group ids if OPERATION_TYPE_MESSAGE
 * @param array $data['opcommand_grp'] list of group ids if OPERATION_TYPE_COMMAND
 * @param array $data['opcommand_hst'] list of host ids if OPERATION_TYPE_COMMAND
 * @param array $data['opgroup'] list of group ids if OPERATION_TYPE_GROUP_ADD or OPERATION_TYPE_GROUP_REMOVE
 * @param array $data['optemplate'] list of template ids if OPERATION_TYPE_TEMPLATE_ADD or OPERATION_TYPE_TEMPLATE_REMOVE
 * @param int $data['operationid'] id of operation
 * @param int $data['opcommand']['type'] type of command: ZBX_SCRIPT_TYPE_IPMI, ZBX_SCRIPT_TYPE_SSH, ...
 * @param string $data['opcommand']['command'] actual command
 * @param int $data['opcommand']['scriptid'] script id used if $data['opcommand']['type'] is ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT
 *
 * @return array
 */
function get_operation_descr($type, $data)
{
    $result = array();
    if ($type == SHORT_DESCRIPTION) {
        switch ($data['operationtype']) {
            case OPERATION_TYPE_MESSAGE:
                $mediaTypes = API::Mediatype()->get(array('mediatypeids' => $data['opmessage']['mediatypeid'], 'output' => array('description')));
                if (empty($mediaTypes)) {
                    $mediatype = _('all media');
                } else {
                    $mediatype = reset($mediaTypes);
                    $mediatype = $mediatype['description'];
                }
                if (!empty($data['opmessage_usr'])) {
                    $users = API::User()->get(array('userids' => zbx_objectValues($data['opmessage_usr'], 'userid'), 'output' => array('userid', 'alias', 'name', 'surname')));
                    order_result($users, 'alias');
                    foreach ($users as $user) {
                        $fullnames[] = getUserFullname($user);
                    }
                    $result[] = bold(_('Send message to users') . NAME_DELIMITER);
                    $result[] = array(implode(', ', $fullnames), SPACE, _('via'), SPACE, $mediatype);
                    $result[] = BR();
                }
                if (!empty($data['opmessage_grp'])) {
                    $usrgrps = API::UserGroup()->get(array('usrgrpids' => zbx_objectValues($data['opmessage_grp'], 'usrgrpid'), 'output' => API_OUTPUT_EXTEND));
                    order_result($usrgrps, 'name');
                    $result[] = bold(_('Send message to user groups') . NAME_DELIMITER);
                    $result[] = array(implode(', ', zbx_objectValues($usrgrps, 'name')), SPACE, _('via'), SPACE, $mediatype);
                    $result[] = BR();
                }
                break;
            case OPERATION_TYPE_COMMAND:
                if (!isset($data['opcommand_grp'])) {
                    $data['opcommand_grp'] = array();
                }
                if (!isset($data['opcommand_hst'])) {
                    $data['opcommand_hst'] = array();
                }
                $hosts = API::Host()->get(array('hostids' => zbx_objectValues($data['opcommand_hst'], 'hostid'), 'output' => array('hostid', 'name')));
                foreach ($data['opcommand_hst'] as $cmd) {
                    if ($cmd['hostid'] != 0) {
                        continue;
                    }
                    $result[] = array(bold(_('Run remote commands on current host')), BR());
                    break;
                }
                if (!empty($hosts)) {
                    order_result($hosts, 'name');
                    $result[] = bold(_('Run remote commands on hosts') . NAME_DELIMITER);
                    $result[] = array(implode(', ', zbx_objectValues($hosts, 'name')), BR());
                }
                $groups = API::HostGroup()->get(array('groupids' => zbx_objectValues($data['opcommand_grp'], 'groupid'), 'output' => array('groupid', 'name')));
                if (!empty($groups)) {
                    order_result($groups, 'name');
                    $result[] = bold(_('Run remote commands on host groups') . NAME_DELIMITER);
                    $result[] = array(implode(', ', zbx_objectValues($groups, 'name')), BR());
                }
                break;
            case OPERATION_TYPE_HOST_ADD:
                $result[] = array(bold(_('Add host')), BR());
                break;
            case OPERATION_TYPE_HOST_REMOVE:
                $result[] = array(bold(_('Remove host')), BR());
                break;
            case OPERATION_TYPE_HOST_ENABLE:
                $result[] = array(bold(_('Enable host')), BR());
                break;
            case OPERATION_TYPE_HOST_DISABLE:
                $result[] = array(bold(_('Disable host')), BR());
                break;
            case OPERATION_TYPE_GROUP_ADD:
            case OPERATION_TYPE_GROUP_REMOVE:
                if (!isset($data['opgroup'])) {
                    $data['opgroup'] = array();
                }
                $groups = API::HostGroup()->get(array('groupids' => zbx_objectValues($data['opgroup'], 'groupid'), 'output' => array('groupid', 'name')));
                if (!empty($groups)) {
                    order_result($groups, 'name');
                    if (OPERATION_TYPE_GROUP_ADD == $data['operationtype']) {
                        $result[] = bold(_('Add to host groups') . NAME_DELIMITER);
                    } else {
                        $result[] = bold(_('Remove from host groups') . NAME_DELIMITER);
                    }
                    $result[] = array(implode(', ', zbx_objectValues($groups, 'name')), BR());
                }
                break;
            case OPERATION_TYPE_TEMPLATE_ADD:
            case OPERATION_TYPE_TEMPLATE_REMOVE:
                if (!isset($data['optemplate'])) {
                    $data['optemplate'] = array();
                }
                $templates = API::Template()->get(array('templateids' => zbx_objectValues($data['optemplate'], 'templateid'), 'output' => array('hostid', 'name')));
                if (!empty($templates)) {
                    order_result($templates, 'name');
                    if (OPERATION_TYPE_TEMPLATE_ADD == $data['operationtype']) {
                        $result[] = bold(_('Link to templates') . NAME_DELIMITER);
                    } else {
                        $result[] = bold(_('Unlink from templates') . NAME_DELIMITER);
                    }
                    $result[] = array(implode(', ', zbx_objectValues($templates, 'name')), BR());
                }
                break;
            default:
        }
    } else {
        switch ($data['operationtype']) {
            case OPERATION_TYPE_MESSAGE:
                if (isset($data['opmessage']['default_msg']) && !empty($data['opmessage']['default_msg'])) {
                    if (isset($_REQUEST['def_shortdata']) && isset($_REQUEST['def_longdata'])) {
                        $result[] = array(bold(_('Subject') . NAME_DELIMITER), BR(), zbx_nl2br($_REQUEST['def_shortdata']));
                        $result[] = array(bold(_('Message') . NAME_DELIMITER), BR(), zbx_nl2br($_REQUEST['def_longdata']));
                    } elseif (isset($data['opmessage']['operationid'])) {
                        $sql = 'SELECT a.def_shortdata,a.def_longdata ' . ' FROM actions a,operations o ' . ' WHERE a.actionid=o.actionid ' . ' AND o.operationid=' . zbx_dbstr($data['operationid']);
                        if ($rows = DBfetch(DBselect($sql, 1))) {
                            $result[] = array(bold(_('Subject') . NAME_DELIMITER), BR(), zbx_nl2br($rows['def_shortdata']));
                            $result[] = array(bold(_('Message') . NAME_DELIMITER), BR(), zbx_nl2br($rows['def_longdata']));
                        }
                    }
                } else {
                    $result[] = array(bold(_('Subject') . NAME_DELIMITER), BR(), zbx_nl2br($data['opmessage']['subject']));
                    $result[] = array(bold(_('Message') . NAME_DELIMITER), BR(), zbx_nl2br($data['opmessage']['message']));
                }
                break;
            case OPERATION_TYPE_COMMAND:
                switch ($data['opcommand']['type']) {
                    case ZBX_SCRIPT_TYPE_IPMI:
                        $result[] = array(bold(_('Run IPMI command') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command'])));
                        break;
                    case ZBX_SCRIPT_TYPE_SSH:
                        $result[] = array(bold(_('Run SSH commands') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command'])));
                        break;
                    case ZBX_SCRIPT_TYPE_TELNET:
                        $result[] = array(bold(_('Run TELNET commands') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command'])));
                        break;
                    case ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT:
                        if ($data['opcommand']['execute_on'] == ZBX_SCRIPT_EXECUTE_ON_AGENT) {
                            $result[] = array(bold(_('Run custom commands on Zabbix agent') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command'])));
                        } else {
                            $result[] = array(bold(_('Run custom commands on Zabbix server') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command'])));
                        }
                        break;
                    case ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT:
                        $userScripts = API::Script()->get(array('scriptids' => $data['opcommand']['scriptid'], 'output' => API_OUTPUT_EXTEND));
                        $userScript = reset($userScripts);
                        $result[] = array(bold(_('Run global script') . NAME_DELIMITER), italic($userScript['name']));
                        break;
                    default:
                        $result[] = array(bold(_('Run commands') . NAME_DELIMITER), BR(), italic(zbx_nl2br($data['opcommand']['command'])));
                }
                break;
            default:
        }
    }
    return $result;
}
Example #4
0
/**
 * Gathers action operation script details and returns the HTML items representing action operation with hint.
 *
 * @param array  $operations								array of action operations
 * @param string $operation['operationtype']				action operation type.
 *															Possible values: OPERATION_TYPE_MESSAGE and OPERATION_TYPE_COMMAND
 * @param string $operation['opcommand']['type']			action operation command type.
 *															Possible values: ZBX_SCRIPT_TYPE_IPMI, ZBX_SCRIPT_TYPE_SSH,
 *															ZBX_SCRIPT_TYPE_TELNET, ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT
 *															and ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT
 * @param string $operation['opmessage']['default_msg']		'1' to show default message (optional)
 * @param array  $defaultMessage							array containing default subject and message set via action
 * @param string $defaultMessage['subject']					default subject
 * @param string $defaultMessage['message']					default message text
 *
 * @return array											returns an array of action operation hints
 */
function getActionOperationHints(array $operations, array $defaultMessage)
{
    $result = [];
    $scriptids = [];
    $scripts = [];
    foreach ($operations as $operation) {
        if ($operation['operationtype'] == OPERATION_TYPE_COMMAND && $operation['opcommand']['type'] == ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT) {
            $scriptids[$operation['opcommand']['scriptid']] = true;
        }
    }
    if ($scriptids) {
        $scripts = API::Script()->get(['output' => ['name'], 'scriptids' => array_keys($scriptids), 'preservekeys' => true]);
    }
    foreach ($operations as $key => $operation) {
        $result[$key] = [];
        switch ($operation['operationtype']) {
            case OPERATION_TYPE_MESSAGE:
                // show default entered action subject and message or show custom subject and message for each operation
                $subject = isset($operation['opmessage']['default_msg']) && $operation['opmessage']['default_msg'] ? $defaultMessage['subject'] : $operation['opmessage']['subject'];
                $message = isset($operation['opmessage']['default_msg']) && $operation['opmessage']['default_msg'] ? $defaultMessage['message'] : $operation['opmessage']['message'];
                $result[$key][] = [bold($subject), BR(), BR(), zbx_nl2br($message)];
                break;
            case OPERATION_TYPE_COMMAND:
                switch ($operation['opcommand']['type']) {
                    case ZBX_SCRIPT_TYPE_IPMI:
                        $result[$key][] = [bold(_('Run IPMI command') . ': '), BR(), italic(zbx_nl2br($operation['opcommand']['command']))];
                        break;
                    case ZBX_SCRIPT_TYPE_SSH:
                        $result[$key][] = [bold(_('Run SSH commands') . ': '), BR(), italic(zbx_nl2br($operation['opcommand']['command']))];
                        break;
                    case ZBX_SCRIPT_TYPE_TELNET:
                        $result[$key][] = [bold(_('Run TELNET commands') . ': '), BR(), italic(zbx_nl2br($operation['opcommand']['command']))];
                        break;
                    case ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT:
                        if ($operation['opcommand']['execute_on'] == ZBX_SCRIPT_EXECUTE_ON_AGENT) {
                            $result[$key][] = [bold(_('Run custom commands on Zabbix agent') . ': '), BR(), italic(zbx_nl2br($operation['opcommand']['command']))];
                        } else {
                            $result[$key][] = [bold(_('Run custom commands on Zabbix server') . ': '), BR(), italic(zbx_nl2br($operation['opcommand']['command']))];
                        }
                        break;
                    case ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT:
                        $scriptId = $operation['opcommand']['scriptid'];
                        if (isset($scripts[$scriptId])) {
                            $result[$key][] = [bold(_('Run global script') . ': '), italic($scripts[$scriptId]['name'])];
                        }
                        break;
                    default:
                        $result[$key][] = [bold(_('Run commands') . ': '), BR(), italic(zbx_nl2br($operation['opcommand']['command']))];
                }
        }
    }
    return $result;
}
        $src = src_expand($src);
    }
    $query = "\n        SELECT\n            source_id,\n            is_unused(source_id) AS unused,\n            get_source_text(source_id) AS src_txt,\n            source_date\n        FROM\n            sources\n        WHERE\n            source_text SIMILAR TO '%{$src}%'\n    ";
    if ($scope != 0) {
        $query .= "\n            AND\n                part_type = {$scope}\n        ";
    }
    if ($yr && $diff) {
        $query .= "\n            AND\n                EXTRACT(YEAR FROM source_date)\n                    BETWEEN {$yr} - {$diff} AND {$yr} + {$diff}\n        ";
    }
    if ($yr && !$diff) {
        $query .= "\n            AND\n                EXTRACT(YEAR FROM source_date) = {$yr}\n        ";
    }
    $query .= "\n        ORDER BY\n            source_date\n    ";
    $handle = pg_query($query);
    echo "<table>\n";
    while ($row = pg_fetch_assoc($handle)) {
        $id = $row['source_id'];
        echo '<tr>';
        echo td_numeric(square_brace(to_url('./source_manager.php', array('node' => $id), $id)));
        if ($row['unused'] == 't') {
            echo td(span_type(square_brace(italic($row['source_date'])) . ' ' . $row['src_txt'], 'faded'));
        } else {
            echo td(square_brace(italic($row['source_date'])) . ' ' . $row['src_txt']);
        }
        echo "</tr>\n";
    }
    echo "</table>\n";
    echo '<p>' . pg_num_rows($handle) . ' treff.</p>';
}
echo "</div>\n";
include "./footer.php";
 *   Copyright (C) 2011 by Leif B. Kristensen <*****@*****.**>        *
 *   All rights reserved. For terms of use, see LICENSE.txt                *
 ***************************************************************************/
// This script is basically a report listing sources of one type.
// It is accessed from the Source Part Type Manager via the 'report' link.
require "./settings/settings.php";
require "./functions.php";
require_once "./langs/{$language}.php";
$spt = $_GET['spt'];
$label = 'label_' . $language;
$spt_name = fetch_val("\n    SELECT {$label} FROM source_part_types WHERE part_type_id = {$spt}\n");
$title = "{$_All} {$_sources} {$_of} type {$spt_name}";
require "./header.php";
echo "<div class=\"normal\">\n";
echo "<h2>{$title}</h2>\n";
echo "<table>";
$handle = pg_query("\n    SELECT\n        source_id,\n        link_expand(source_text) AS txt,\n        source_date,\n        ecc(source_id) AS e,\n        rcc(source_id) AS r,\n        ssc(source_id) AS s,\n        usc(source_id) AS u,\n        spt.{$label} AS {$label}\n    FROM\n        sources, source_part_types spt\n    WHERE\n        spt.part_type_id = sources.part_type\n    AND\n        spt.part_type_id = {$spt}\n    AND\n        source_id <> 0\n    ORDER BY\n        source_date,\n        source_text\n");
while ($row = pg_fetch_assoc($handle)) {
    $id = $row['source_id'];
    echo '<tr>';
    echo td(paren(to_url('source_manager.php', array('node' => $id), $_Select) . '&nbsp;/&nbsp;' . to_url('./forms/source_edit.php', array('person' => 0, 'source' => $id), $_Edit)));
    if ($row['e'] || $row['r'] || $row['s']) {
        echo td(square_brace(italic($row['source_date'])) . ' ' . $row['txt'] . node_details($row['e'], $row['r'], $row['s'], $row['u']));
    } else {
        // source is unused, print with gray text
        echo td(span_type(square_brace(italic($row['source_date'])) . conc($row['txt']), "faded"));
    }
    echo "</tr>\n";
}
echo "</table>\n";
include "./footer.php";
Example #7
0
    echo "<h4>{$_Sources}</h4>\n";
    echo "<ol class=\"sources\">\n";
    while ($sources = pg_fetch_assoc($handle)) {
        echo li(($sources['part_type'] == 0 ? span_type($sources['source_text'], 'alert') : $sources['source_text']) . conc(span_type(paren(to_url('./forms/source_edit.php', array('person' => $person, 'source' => $sources['source_id']), $_edit) . ' / ' . to_url('./forms/source_select.php', array('person' => $person, 'source' => $sources['source_id']), $_use)), "hotlink")));
    }
    echo "</ol>\n";
}
// new section: "mentioned in sources"
if (fetch_val("SELECT COUNT(*) FROM source_linkage WHERE person_fk={$person}")) {
    echo "<h3>Nevnt i kilder:</h3>\n";
    $label = 'label_' . $language;
    $handle = pg_query("\n        SELECT\n            s.source_id AS source,\n            l.per_id AS per_id,\n            spt.{$label} AS s_type,\n            get_lsurety(l.surety_fk) AS surety,\n            get_lrole(l.role_fk) AS rolle,\n            l.s_name AS name,\n            get_source_text(s.source_id) AS txt,\n            link_expand(l.sl_note) AS note\n        FROM\n            sources s,\n            source_linkage l,\n            source_part_types spt\n        WHERE\n            l.source_fk = s.source_id\n        AND\n            l.person_fk = {$person}\n        AND\n            spt.part_type_id = s.part_type\n        ORDER BY\n            s.source_date\n    ");
    echo "<ol>\n";
    while ($row = pg_fetch_assoc($handle)) {
        if ($principal = fetch_val("\n            SELECT person_fk FROM source_linkage\n            WHERE source_fk = " . $row['source'] . " AND role_fk = 1\n        ")) {
            echo li($row['s_type'] . conc(linked_name($principal), ' av ') . conc($row['surety'], ', ') . conc($row['rolle']) . ' «' . $row['name'] . '»<br />' . $row['txt'] . conc(italic($row['note'])) . conc(paren(to_url("{$app_path}/forms/linkage_edit.php", array('node' => $row['source'], 'id' => $row['per_id'], 'person' => $person), $_edit))));
        }
    }
    echo "</ol>\n";
}
// conditionally print spouses and children
if (has_spouses($person) || has_descendants($person)) {
    if (has_descendants($person)) {
        // create and populate temporary children table
        pg_query("\n            CREATE TEMPORARY TABLE tmp_children (\n                child INTEGER PRIMARY KEY,\n                coparent INTEGER,\n                pb_date CHAR(18)\n            )");
        pg_query("\n            INSERT INTO tmp_children\n                SELECT\n                    child_fk,\n                    get_coparent({$person}, child_fk),\n                    get_pbdate(child_fk) AS pbd\n                FROM\n                    relations\n                WHERE\n                    parent_fk = {$person}\n                ORDER BY\n                    pbd\n            ");
    }
    echo "<h3>{$_Family}</h3>\n";
    // get spouses
    $handle = pg_query("\n        SELECT\n            spouse\n        FROM\n            marriages\n        WHERE\n            person = {$person}\n        ");
    while ($spouses = pg_fetch_row($handle)) {
function make_disp_tree($tree, $map, $action = false)
{
    $res = array();
    foreach ($tree as $i => $n) {
        $expr = array();
        for ($j = 0; $j < $n['depth']; ++$j) {
            $next = $finder($tree, $i + 1, $j + 1);
            if ($j + 1 == $n['depth']) {
                $expr[] = new CImg('images/general/tr_' . ($next ? 'top_right_bottom' : 'top_right') . '.gif', 'tr', 12, 12);
            } else {
                $expr[] = new CImg('images/general/tr_' . ($next ? 'top_bottom' : 'space') . '.gif', 'tr', 12, 12);
            }
        }
        $key = null;
        if (zbx_strlen($n['expr']) == 1) {
            $key = $n['expr'];
            $tgt = $map[$key];
            array_push($expr, SPACE, bold($n['expr']), SPACE);
            $e = $tgt['expression'] . $tgt['sign'] . $tgt['value'];
            if ($action) {
                $url = new CSpan($e, 'link');
                $url->setAttribute('id', 'expr' . $n['id']);
                $url->setAttribute('onclick', 'javascript: copy_expression("expr' . $n['id'] . '");');
                $expr[] = $url;
            } else {
                $expr[] = $e;
            }
        } else {
            array_push($expr, SPACE, italic($n['expr']));
        }
        array_push($res, array('id' => $n['id'], 'expr' => $expr, 'key' => $key));
    }
    return $res;
}