17Syaroslav@ivinco.com<?php
27Syaroslav@ivinco.com/*
37Syaroslav@ivinco.com * To change this template, choose Tools | Templates
47Syaroslav@ivinco.com * and open the template in the editor.
57Syaroslav@ivinco.com */
67Syaroslav@ivinco.com
77Syaroslav@ivinco.comfunction formatXml($data)
87Syaroslav@ivinco.com{
97Syaroslav@ivinco.com    $xmlFormat = '
107Syaroslav@ivinco.com<sphinx:document id="{id}">
117Syaroslav@ivinco.com<title><![CDATA[[{title}]]></title>
127Syaroslav@ivinco.com<body><![CDATA[[{body}]]></body>
1380Syaroslav@ivinco.com<namespace><![CDATA[[{namespace}]]></namespace>
1480Syaroslav@ivinco.com<pagename><![CDATA[[{pagename}]]></pagename>
157Syaroslav@ivinco.com<level>{level}</level>
1637Syaroslav@ivinco.com<modified>{modified}</modified>
177Syaroslav@ivinco.com</sphinx:document>
187Syaroslav@ivinco.com
197Syaroslav@ivinco.com';
207Syaroslav@ivinco.com
2180Syaroslav@ivinco.com    return str_replace( array('{id}', '{title}', '{body}', '{namespace}', '{pagename}', '{level}', '{modified}'),
2280Syaroslav@ivinco.com                        array($data['id'], escapeTextValue($data['title_to_index']),
2380Syaroslav@ivinco.com                            escapeTextValue($data['body']),
2480Syaroslav@ivinco.com                            escapeTextValue($data['namespace']),
2580Syaroslav@ivinco.com                            escapeTextValue($data['pagename']),
2612Syaroslav@ivinco.com                             $data['level'], $data['modified']),
277Syaroslav@ivinco.com                $xmlFormat
287Syaroslav@ivinco.com            );
297Syaroslav@ivinco.com}
307Syaroslav@ivinco.com
3137Syaroslav@ivinco.comfunction escapeTextValue($value)
3237Syaroslav@ivinco.com{
3337Syaroslav@ivinco.com    if ("" === $value)
3437Syaroslav@ivinco.com    {
3537Syaroslav@ivinco.com        return "";
3637Syaroslav@ivinco.com    }
3758Syaroslav@ivinco.com    //$value = mb_convert_encoding($value,'UTF-8','ISO-8859-1');
3837Syaroslav@ivinco.com    $value = strip_tags($value);
3937Syaroslav@ivinco.com    $value = stripInvalidXml($value);
4037Syaroslav@ivinco.com    return str_replace("]]>", "]]><![CDATA[]]]]><![CDATA[>]]><![CDATA[", $value);
4137Syaroslav@ivinco.com }
4237Syaroslav@ivinco.com
4337Syaroslav@ivinco.comfunction stripInvalidXml($value)
4437Syaroslav@ivinco.com{
4537Syaroslav@ivinco.com    $ret = "";
4637Syaroslav@ivinco.com    if (empty($value))
4737Syaroslav@ivinco.com    {
4837Syaroslav@ivinco.com      return $ret;
4937Syaroslav@ivinco.com    }
5037Syaroslav@ivinco.com
5137Syaroslav@ivinco.com    $current = null;
5237Syaroslav@ivinco.com    $length = strlen($value);
5337Syaroslav@ivinco.com    for ($i=0; $i < $length; $i++)
5437Syaroslav@ivinco.com    {
5537Syaroslav@ivinco.com      $current = ord($value{$i});
5637Syaroslav@ivinco.com      if (($current == 0x9) ||
5737Syaroslav@ivinco.com          ($current == 0xA) ||
5837Syaroslav@ivinco.com          ($current == 0xD) ||
5937Syaroslav@ivinco.com          (($current >= 0x20) && ($current <= 0xD7FF)) ||
6037Syaroslav@ivinco.com          (($current >= 0xE000) && ($current <= 0xFFFD)) ||
6137Syaroslav@ivinco.com          (($current >= 0x10000) && ($current <= 0x10FFFF)))
6237Syaroslav@ivinco.com      {
6337Syaroslav@ivinco.com        $ret .= chr($current);
6437Syaroslav@ivinco.com      }
6537Syaroslav@ivinco.com      else
6637Syaroslav@ivinco.com      {
6737Syaroslav@ivinco.com        $ret .= " ";
6837Syaroslav@ivinco.com      }
6937Syaroslav@ivinco.com    }
7037Syaroslav@ivinco.com    return $ret;
7137Syaroslav@ivinco.com  }
7237Syaroslav@ivinco.com
737Syaroslav@ivinco.comfunction getDocumentsByHeadings($id, $metadata)
747Syaroslav@ivinco.com{
757Syaroslav@ivinco.com    if (empty($metadata) || empty($metadata['description']['tableofcontents'])) return false;
767Syaroslav@ivinco.com
777Syaroslav@ivinco.com    $sections = array();
7819Syaroslav@ivinco.com    $level = 1;
7919Syaroslav@ivinco.com    $previouse_title = '';
807Syaroslav@ivinco.com    foreach($metadata['description']['tableofcontents'] as $row){
817Syaroslav@ivinco.com        $sections[$row['hid']] = array(
8220Syaroslav@ivinco.com                                    'section' => getSectionByTitleLevel($id, $row['title']),
8319Syaroslav@ivinco.com                                    'level' => $row['level'],
8419Syaroslav@ivinco.com                                    'title' => $row['title']
857Syaroslav@ivinco.com                                    );
8656Syaroslav@ivinco.com        if ($row['level'] > $level && !empty($previouse_title)){
8719Syaroslav@ivinco.com            $sections[$row['hid']]['title_text'] = $previouse_title . " &raquo; ".$row['title'];
8819Syaroslav@ivinco.com        } else {
8919Syaroslav@ivinco.com            $sections[$row['hid']]['title_text'] = $row['title'];
9019Syaroslav@ivinco.com            $previouse_title = $row['title'];
9119Syaroslav@ivinco.com        }
9256Syaroslav@ivinco.com        $sections[$row['hid']]['title_to_index'] = $row['title'];
937Syaroslav@ivinco.com    }
947Syaroslav@ivinco.com    return $sections;
957Syaroslav@ivinco.com}
967Syaroslav@ivinco.com
9721Syaroslav@ivinco.comfunction getSectionByTitleLevel($id, $header, $extended=false)
9820Syaroslav@ivinco.com{
9920Syaroslav@ivinco.com    $headerReg = preg_quote($header, '/');
10020Syaroslav@ivinco.com    $doc = io_readFile(wikiFN($id));
10135Syaroslav@ivinco.com    $regex = "(={1,6})\s*({$headerReg})\s*(={1,6})";
10220Syaroslav@ivinco.com    $section = '';
10320Syaroslav@ivinco.com    if (preg_match("/$regex/i",$doc,$matches)) {
10420Syaroslav@ivinco.com        $startHeader = $matches[0];
10520Syaroslav@ivinco.com        $startHeaderPos = strpos($doc, $startHeader) + strlen($startHeader);
10620Syaroslav@ivinco.com        $endDoc = substr($doc, $startHeaderPos);
10720Syaroslav@ivinco.com
108*96Syaroslav@ivinco.com        $regex = '(={4,6})(.*?)(={4,6})';
10920Syaroslav@ivinco.com        if (preg_match("/$regex/i",$endDoc,$matches)) {
11020Syaroslav@ivinco.com            $endHeader = $matches[0];
11120Syaroslav@ivinco.com            $endHeaderPos = strpos($doc, $endHeader);
11220Syaroslav@ivinco.com        } else {
11320Syaroslav@ivinco.com            $endHeaderPos = 0;
11420Syaroslav@ivinco.com        }
11520Syaroslav@ivinco.com        if ($endHeaderPos){
11620Syaroslav@ivinco.com            $section = substr($doc, $startHeaderPos, $endHeaderPos - $startHeaderPos);
11720Syaroslav@ivinco.com        } else {
11820Syaroslav@ivinco.com            $section = substr($doc, $startHeaderPos);
11920Syaroslav@ivinco.com        }
12020Syaroslav@ivinco.com    }
12120Syaroslav@ivinco.com    $section = trim($section);
12221Syaroslav@ivinco.com    //trying to get next section content if body for first section is empty
12321Syaroslav@ivinco.com    //working only for extended mode
12421Syaroslav@ivinco.com    if ($extended && empty($section)){
12520Syaroslav@ivinco.com        $startHeaderPos = $endHeaderPos + strlen($endHeader);
12620Syaroslav@ivinco.com        $endDoc = substr($endDoc, $startHeaderPos);
127*96Syaroslav@ivinco.com        $regex = '(={4,6})(.*?)(={4,6})';
12820Syaroslav@ivinco.com        if (preg_match("/$regex/i",$endDoc,$matches)) {
12920Syaroslav@ivinco.com            $endHeader = $matches[0];
13020Syaroslav@ivinco.com            $endHeaderPos = strpos($doc, $endHeader);
13120Syaroslav@ivinco.com        } else {
13220Syaroslav@ivinco.com            $endHeaderPos = 0;
13320Syaroslav@ivinco.com        }
13420Syaroslav@ivinco.com        if ($endHeaderPos){
13520Syaroslav@ivinco.com            $section = substr($doc, $startHeaderPos, $endHeaderPos - $startHeaderPos);
13620Syaroslav@ivinco.com        } else {
13720Syaroslav@ivinco.com            $section = substr($doc, $startHeaderPos);
13820Syaroslav@ivinco.com        }
13920Syaroslav@ivinco.com    }
14021Syaroslav@ivinco.com    $section = trim($section);
14120Syaroslav@ivinco.com    return $section;
14220Syaroslav@ivinco.com}
14320Syaroslav@ivinco.com
1447Syaroslav@ivinco.comfunction getSection($id, $header)
1457Syaroslav@ivinco.com{
14617Syaroslav@ivinco.com    static $cacheInstructions = null;
14717Syaroslav@ivinco.com    static $cacheDoc = null;
14817Syaroslav@ivinco.com
14918Syaroslav@ivinco.com    if (empty($cacheDoc[$id])){
15017Syaroslav@ivinco.com        // Create the parser
15117Syaroslav@ivinco.com        $Parser = & new Doku_Parser();
1527Syaroslav@ivinco.com
15317Syaroslav@ivinco.com        // Add the Handler
15417Syaroslav@ivinco.com        $Parser->Handler = & new Doku_Handler();
15517Syaroslav@ivinco.com
15617Syaroslav@ivinco.com        // Load the header mode to find headers
15717Syaroslav@ivinco.com        $Parser->addMode('header',new Doku_Parser_Mode_Header());
15818Syaroslav@ivinco.com        $Parser->addMode('listblock',new Doku_Parser_Mode_ListBlock());
15917Syaroslav@ivinco.com
16017Syaroslav@ivinco.com        // Loads the raw wiki document
16117Syaroslav@ivinco.com        $doc = io_readFile(wikiFN($id));
1627Syaroslav@ivinco.com
16317Syaroslav@ivinco.com        // Get a list of instructions
16417Syaroslav@ivinco.com        $instructions = $Parser->parse($doc);
16517Syaroslav@ivinco.com
16617Syaroslav@ivinco.com        unset($Parser->Handler);
16717Syaroslav@ivinco.com        unset($Parser);
16817Syaroslav@ivinco.com
16917Syaroslav@ivinco.com        //free old cache
17018Syaroslav@ivinco.com        $cacheInstructions = null;
17118Syaroslav@ivinco.com        $cacheDoc = null;
1727Syaroslav@ivinco.com
17317Syaroslav@ivinco.com        //initialize new cache
17418Syaroslav@ivinco.com        $cacheInstructions[$id] = $instructions;
17518Syaroslav@ivinco.com        $cacheDoc[$id] = $doc;
17617Syaroslav@ivinco.com    } else {
17717Syaroslav@ivinco.com        $instructions = $cacheInstructions[$id];
17817Syaroslav@ivinco.com        $doc = $cacheDoc[$id];
17918Syaroslav@ivinco.com    }
1807Syaroslav@ivinco.com
18117Syaroslav@ivinco.com
1827Syaroslav@ivinco.com
1837Syaroslav@ivinco.com    // Use this to watch when we're inside the section we want
1847Syaroslav@ivinco.com    $inSection = FALSE;
1857Syaroslav@ivinco.com    $startPos = 0;
1867Syaroslav@ivinco.com    $endPos = 0;
1877Syaroslav@ivinco.com
1887Syaroslav@ivinco.com    // Loop through the instructions
1897Syaroslav@ivinco.com    foreach ( $instructions as $instruction ) {
1907Syaroslav@ivinco.com
1917Syaroslav@ivinco.com        if ( !$inSection ) {
1927Syaroslav@ivinco.com
1937Syaroslav@ivinco.com            // Look for the header for the "Lists" heading
1947Syaroslav@ivinco.com            if ( $instruction[0] == 'header' &&
1957Syaroslav@ivinco.com                    trim($instruction[1][0]) == $header ) {
1967Syaroslav@ivinco.com
1977Syaroslav@ivinco.com                $startPos = $instruction[2];
1987Syaroslav@ivinco.com                $inSection = TRUE;
1997Syaroslav@ivinco.com            }
2007Syaroslav@ivinco.com        } else {
2017Syaroslav@ivinco.com
2027Syaroslav@ivinco.com            // Look for the end of the section
2037Syaroslav@ivinco.com            if ( $instruction[0] == 'section_close' ) {
2047Syaroslav@ivinco.com                $endPos = $instruction[2];
2057Syaroslav@ivinco.com                break;
2067Syaroslav@ivinco.com            }
2077Syaroslav@ivinco.com        }
2087Syaroslav@ivinco.com    }
2097Syaroslav@ivinco.com
2107Syaroslav@ivinco.com    // Normalize and pad the document in the same way the parse does
2117Syaroslav@ivinco.com    // so that byte indexes with match
2127Syaroslav@ivinco.com    $doc = "\n".str_replace("\r\n","\n",$doc)."\n";
2137Syaroslav@ivinco.com    $section = substr($doc, $startPos, ($endPos-$startPos));
2147Syaroslav@ivinco.com
2157Syaroslav@ivinco.com    return $section;
2167Syaroslav@ivinco.com}
2177Syaroslav@ivinco.com
2187Syaroslav@ivinco.comfunction getCategories($id)
2197Syaroslav@ivinco.com{
2207Syaroslav@ivinco.com    if (empty($id)) return '';
2217Syaroslav@ivinco.com
2227Syaroslav@ivinco.com    if (false === strpos($id, ":")){
22380Syaroslav@ivinco.com        return '';
2247Syaroslav@ivinco.com    }
2257Syaroslav@ivinco.com
2267Syaroslav@ivinco.com    $ns = explode(":", $id);
22780Syaroslav@ivinco.com    $nsCount = count($ns) - 1;
2287Syaroslav@ivinco.com
2297Syaroslav@ivinco.com    $result = '';
2307Syaroslav@ivinco.com    do{
2317Syaroslav@ivinco.com        for($i = 0; $i < $nsCount; $i++){
2327Syaroslav@ivinco.com            $name = $ns[$i];
2337Syaroslav@ivinco.com            $result .= $name;
2347Syaroslav@ivinco.com            if ($i < $nsCount - 1){
2357Syaroslav@ivinco.com                 $result .= ':';
2367Syaroslav@ivinco.com            }
2377Syaroslav@ivinco.com        }
2387Syaroslav@ivinco.com        $result .= ' ';
2397Syaroslav@ivinco.com    }while($nsCount--);
2407Syaroslav@ivinco.com    return $result;
2417Syaroslav@ivinco.com}
2427Syaroslav@ivinco.com
24380Syaroslav@ivinco.comfunction getPagename($id)
24480Syaroslav@ivinco.com{
24580Syaroslav@ivinco.com    if (empty($id)) return '';
24680Syaroslav@ivinco.com
24780Syaroslav@ivinco.com    if (false === strpos($id, ":")){
24880Syaroslav@ivinco.com        return $id;
24980Syaroslav@ivinco.com    }
25080Syaroslav@ivinco.com
25180Syaroslav@ivinco.com    $ns = explode(":", $id);
25280Syaroslav@ivinco.com    return $ns[count($ns) - 1];
25380Syaroslav@ivinco.com}
25480Syaroslav@ivinco.com
25580Syaroslav@ivinco.com
2567Syaroslav@ivinco.com
2577Syaroslav@ivinco.com /**
2587Syaroslav@ivinco.com  * Method return all wiki page names
2597Syaroslav@ivinco.com  * @global array $conf
2607Syaroslav@ivinco.com  * @return array
2617Syaroslav@ivinco.com  */
2627Syaroslav@ivinco.com function getPagesList()
2637Syaroslav@ivinco.com {
2647Syaroslav@ivinco.com    global $conf;
2657Syaroslav@ivinco.com
2667Syaroslav@ivinco.com    $data = array();
2677Syaroslav@ivinco.com    sort($data);
2687Syaroslav@ivinco.com    search($data,$conf['datadir'],'search_allpages','','');
2697Syaroslav@ivinco.com
2707Syaroslav@ivinco.com    return $data;
2718Syaroslav@ivinco.com}
2728Syaroslav@ivinco.com
27315Syaroslav@ivinco.comfunction getNsLinks($id, $keywords, $search)
2748Syaroslav@ivinco.com{
2758Syaroslav@ivinco.com    global $conf;
2768Syaroslav@ivinco.com    $parts = explode(':', $id);
2778Syaroslav@ivinco.com    $count = count($parts);
27815Syaroslav@ivinco.com
2798Syaroslav@ivinco.com    // print intermediate namespace links
2808Syaroslav@ivinco.com    $part = '';
28110Syaroslav@ivinco.com    $data = array();
28210Syaroslav@ivinco.com    $titles = array();
2838Syaroslav@ivinco.com    for($i=0; $i<$count; $i++){
2848Syaroslav@ivinco.com        $part .= $parts[$i].':';
2858Syaroslav@ivinco.com        $page = $part;
2868Syaroslav@ivinco.com        resolve_pageid('',$page,$exists);
28715Syaroslav@ivinco.com
28815Syaroslav@ivinco.com        if (preg_match("#:start$#", $page) && !preg_match("#:start:$#", $part)) {
28913Syaroslav@ivinco.com            $page = substr($page, 0, strpos($page, ":start"));
29013Syaroslav@ivinco.com        };
2918Syaroslav@ivinco.com
2928Syaroslav@ivinco.com        // output
2938Syaroslav@ivinco.com        if ($exists){
29415Syaroslav@ivinco.com            $titles[wl($page)] = $parts[$i];
2958Syaroslav@ivinco.com        } else {
29618Syaroslav@ivinco.com            $titles[wl($page)] = $parts[$i];
29715Syaroslav@ivinco.com        }
29882Syaroslav@ivinco.com        $data[] = array('link' => "?do=search&id={$keywords}".urlencode(" @ns $page"));
2998Syaroslav@ivinco.com    }
30015Syaroslav@ivinco.com    $titleExcerpt = $search->getExcerpt($titles, $search->starQuery($keywords));
30110Syaroslav@ivinco.com    $i = 0;
30210Syaroslav@ivinco.com    foreach ($data as $key => $notused){
30310Syaroslav@ivinco.com        $data[$key]['title'] = $titleExcerpt[$i++];
30410Syaroslav@ivinco.com    }
30510Syaroslav@ivinco.com    return $data;
30639Syaroslav@ivinco.com}
30739Syaroslav@ivinco.com
30839Syaroslav@ivinco.comfunction printNamespaces($query)
30939Syaroslav@ivinco.com{
31039Syaroslav@ivinco.com  $data = array();
31161Syaroslav@ivinco.com  $query = str_replace(" ", "_", $query);
31269Syaroslav@ivinco.com  $data = ft_pageLookup($query, false);
31339Syaroslav@ivinco.com
31453Syaroslav@ivinco.com  if(!count($data)) return false;
31539Syaroslav@ivinco.com
31653Syaroslav@ivinco.com  print '<h3>Matching pagenames</h3>';
31739Syaroslav@ivinco.com  print '<ul>';
31848Syaroslav@ivinco.com  $counter = 0;
31939Syaroslav@ivinco.com  foreach($data as $id){
32039Syaroslav@ivinco.com    print '<li>';
32139Syaroslav@ivinco.com    $ns = getNS($id);
32239Syaroslav@ivinco.com    if($ns){
32339Syaroslav@ivinco.com      $name = shorten(noNS($id), ' ('.$ns.')',30);
32439Syaroslav@ivinco.com    }else{
32539Syaroslav@ivinco.com      $name = $id;
32639Syaroslav@ivinco.com    }
32761Syaroslav@ivinco.com    $href = wl($id);
32861Syaroslav@ivinco.com
32950Syaroslav@ivinco.com    tpl_link($href,$id, "class='wikilink1'");
33039Syaroslav@ivinco.com    print '</li>';
33148Syaroslav@ivinco.com    if(++$counter == 20){
33248Syaroslav@ivinco.com        break;
33348Syaroslav@ivinco.com    }
33439Syaroslav@ivinco.com  }
33539Syaroslav@ivinco.com  print '</ul>';
33668Syaroslav@ivinco.com}
33768Syaroslav@ivinco.com
33869Syaroslav@ivinco.comfunction printNamespacesNew($pageNames)
33968Syaroslav@ivinco.com{
34069Syaroslav@ivinco.com    if(empty($pageNames)) return false;
34168Syaroslav@ivinco.com
34270Syaroslav@ivinco.com    $limit = 10;
34368Syaroslav@ivinco.com    print '<h3>Matching pagenames</h3>';
34468Syaroslav@ivinco.com    print '<ul>';
34570Syaroslav@ivinco.com    $counter = 0;
34677Syaroslav@ivinco.com    foreach($pageNames as $id => $header){
34776Syaroslav@ivinco.com        $ns = getNS($id);
34876Syaroslav@ivinco.com        if($ns){
34976Syaroslav@ivinco.com          $name = shorten(noNS($id), ' ('.$ns.')',30);
35076Syaroslav@ivinco.com        }else{
35176Syaroslav@ivinco.com          $name = $id;
35276Syaroslav@ivinco.com        }
35368Syaroslav@ivinco.com        print '<li>';
35481Syaroslav@ivinco.com        /*if (!empty($header)){
35577Syaroslav@ivinco.com            print '<a href="'.wl($id).'#'.$header.'" '. "class='wikilink1'>".$id."</a>".'#'.$header;
35677Syaroslav@ivinco.com        } else {
35777Syaroslav@ivinco.com            print '<a href="'.wl($id).'" '. "class='wikilink1'>".$id."</a>";
35881Syaroslav@ivinco.com        }*/
35981Syaroslav@ivinco.com        print '<a href="'.wl($id).'" '. "class='wikilink1'>".$id."</a>";
36068Syaroslav@ivinco.com        print '</li>';
36170Syaroslav@ivinco.com        if (++$counter == $limit){
36270Syaroslav@ivinco.com            break;
36370Syaroslav@ivinco.com        }
36468Syaroslav@ivinco.com    }
36568Syaroslav@ivinco.com    print '</ul>';
36694Syaroslav@ivinco.com}
36794Syaroslav@ivinco.com
36894Syaroslav@ivinco.comif(!function_exists('shorten')){
36994Syaroslav@ivinco.com    /**
37094Syaroslav@ivinco.com     * Shorten a given string by removing data from the middle
37194Syaroslav@ivinco.com     *
37294Syaroslav@ivinco.com     * You can give the string in two parts, teh first part $keep
37394Syaroslav@ivinco.com     * will never be shortened. The second part $short will be cut
37494Syaroslav@ivinco.com     * in the middle to shorten but only if at least $min chars are
37594Syaroslav@ivinco.com     * left to display it. Otherwise it will be left off.
37694Syaroslav@ivinco.com     *
37794Syaroslav@ivinco.com     * @param string $keep   the part to keep
37894Syaroslav@ivinco.com     * @param string $short  the part to shorten
37994Syaroslav@ivinco.com     * @param int    $max    maximum chars you want for the whole string
38094Syaroslav@ivinco.com     * @param int    $min    minimum number of chars to have left for middle shortening
38194Syaroslav@ivinco.com     * @param string $char   the shortening character to use
38294Syaroslav@ivinco.com     */
38394Syaroslav@ivinco.com    function shorten($keep,$short,$max,$min=9,$char='⌇'){
38494Syaroslav@ivinco.com        $max = $max - utf8_strlen($keep);
38594Syaroslav@ivinco.com       if($max < $min) return $keep;
38694Syaroslav@ivinco.com        $len = utf8_strlen($short);
38794Syaroslav@ivinco.com        if($len <= $max) return $keep.$short;
38894Syaroslav@ivinco.com        $half = floor($max/2);
38994Syaroslav@ivinco.com        return $keep.utf8_substr($short,0,$half-1).$char.utf8_substr($short,$len-$half);
39094Syaroslav@ivinco.com    }
39194Syaroslav@ivinco.com}
392