Example #1
0
 /**
  * search 
  * 
  * @param array $pSearchHash basically the same parameters as a regular list
  * @access public
  * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  */
 function search(&$pSearchHash)
 {
     // PHP compatability issues
     include_once UTIL_PKG_PATH . 'PHP_Compat/Compat/Function/stripos.php';
     global $gLibertySystem, $gBitSystem, $gBitUser, $gBitDbType;
     // initiate stuff
     BitBase::prepGetList($pSearchHash);
     $ret = $bindVars = array();
     $selectSql = $whereSql = $orderSql = $joinSql = '';
     // if all content has been selected, there is an empty value in the array
     if (isset($pSearchHash['content_type_guid']) && !is_array($pSearchHash['content_type_guid'])) {
         $pSearchHash['content_type_guid'] = array($pSearchHash['content_type_guid']);
     }
     if (!empty($pSearchHash['content_type_guid']) && in_array('', $pSearchHash['content_type_guid'])) {
         $pSearchHash['content_type_guid'] = array();
     }
     // check if the user has the required permissions to view the requested content type
     foreach ($gLibertySystem->mContentTypes as $contentType) {
         if ((empty($pSearchHash['content_type_guid']) || in_array($contentType["content_type_guid"], $pSearchHash['content_type_guid'])) && $this->hasViewPermission($contentType["content_type_guid"])) {
             $allowed[] = $contentType["content_type_guid"];
         }
     }
     if (in_array('bitcomment', $allowed)) {
         $pSearchHash['include_comments'] = TRUE;
     }
     if (!empty($allowed)) {
         $whereSql .= empty($whereSql) ? ' WHERE ' : ' AND ';
         $whereSql .= " lc.`content_type_guid` IN( " . implode(',', array_fill(0, count($allowed), '?')) . " ) ";
         $bindVars = array_merge($bindVars, $allowed);
     } else {
         $this->mErrors['permission'] = tra("You don't have the required permissions to search the requested content types.");
     }
     // create valid search SQL
     if ($errors = $this->prepareSearchSql($pSearchHash, $whereSql, $bindVars)) {
         $this->mErrors = $errors;
     }
     // get service SQL
     LibertyContent::getServicesSql('content_list_sql_function', $selectSql, $joinSql, $whereSql, $bindVars, NULL, $pSearchHash);
     if (!empty($pSearchHash['sort_mode'])) {
         $orderSql = " ORDER BY lc." . $this->mDb->convertSortmode($pSearchHash['sort_mode']);
     }
     // only continue if we haven't choked so far
     if (empty($this->mErrors)) {
         $query = "\n\t\t\t\tSELECT \n\t\t\t\tuue.`login` AS `modifier_user`,\n\t\t\t\tuue.`real_name` AS `modifier_real_name`,\n\t\t\t\tuue.`user_id` AS `modifier_user_id`,\n\t\t\t\tuuc.`login` AS `creator_user`,\n\t\t\t\tuuc.`real_name` AS `creator_real_name`,\n\t\t\t\tuuc.`user_id` AS `creator_user_id`,\n\t\t\t\tlc.`data`, \n\t\t\t\tlc.`content_id`, \n\t\t\t\tlc.`title`, \n\t\t\t\tlcds.`data` AS `summary`, \n\t\t\t\tlct.`content_name`, \n\t\t\t\tlct.`content_name_plural`, \n\t\t\t\tlch.`hits`,  \n\t\t\t\tlc.`last_modified`,\n\t\t\t\tlc.`created`,\n\t\t\t\tlc.`content_type_guid`\n\t\t\t\t{$selectSql}\n\t\t\t\tFROM `" . BIT_DB_PREFIX . "liberty_content` lc\n\t\t\t\t\tINNER JOIN `" . BIT_DB_PREFIX . "users_users` uuc ON (lc.`user_id`=uuc.`user_id`)\n\t\t\t\t\tINNER JOIN `" . BIT_DB_PREFIX . "users_users` uue ON (lc.`modifier_user_id`=uue.`user_id`)\n\t\t\t\t\tLEFT OUTER JOIN `" . BIT_DB_PREFIX . "liberty_content_data` lcds ON ( lc.`content_id` = lcds.`content_id` AND lcds.`data_type` = 'summary' )\n\t\t\t\t\tLEFT OUTER JOIN `" . BIT_DB_PREFIX . "liberty_content_types` lct ON ( lc.`content_type_guid` = lct.`content_type_guid` )\n\t\t\t\t\tLEFT OUTER JOIN `" . BIT_DB_PREFIX . "liberty_content_hits` lch ON ( lc.`content_id` = lch.`content_id` )\n\t\t\t\t{$joinSql} {$whereSql} {$orderSql}";
         $result = $this->mDb->query($query, $bindVars, $pSearchHash['max_records'], $pSearchHash['offset']);
         while ($aux = $result->fetchRow()) {
             $data = $aux['summary'] . "\n" . $aux['data'];
             $aux['len'] = strlen($data);
             $lines = explode("\n", strip_tags($data));
             foreach ($pSearchHash['findHash'] as $val) {
                 $val = trim($val, "%");
                 $i = 0;
                 foreach ($lines as $number => $line) {
                     if ($i < 3 && !empty($line) && stripos($line, $val) !== FALSE) {
                         $aux['display_lines'][$number + 1] = encode_email_addresses($line);
                         $i++;
                     }
                 }
                 if (!empty($aux['display_lines'])) {
                     ksort($aux['display_lines']);
                 }
             }
             $aux['display_url'] = BIT_ROOT_URL . "index.php?content_id=" . $aux['content_id'];
             $ret[] = $aux;
         }
         // do some custom sorting
         usort($ret, 'ilike_relevance_sort');
         $query = "\n\t\t\t\tSELECT COUNT( lc.`content_id` )\n\t\t\t\tFROM `" . BIT_DB_PREFIX . "liberty_content` lc\n\t\t\t\t\tLEFT OUTER JOIN `" . BIT_DB_PREFIX . "liberty_content_data` lcds ON ( lc.`content_id` = lcds.`content_id` )\n\t\t\t\t\tLEFT OUTER JOIN `" . BIT_DB_PREFIX . "liberty_content_types` lct ON ( lc.`content_type_guid` = lct.`content_type_guid` )\n\t\t\t\t{$joinSql} {$whereSql}";
         $pSearchHash['cant'] = $this->mDb->getOne($query, $bindVars);
         BitBase::postGetList($pSearchHash);
         return $ret;
     } else {
         return FALSE;
     }
 }
Example #2
0
 function parseData($pParseHash, &$pCommonObject)
 {
     global $gBitSystem, $gLibertySystem, $gBitUser, $page;
     $data = $pParseHash['data'];
     $contentId = $pParseHash['content_id'];
     // this is used for setting the links when section editing is enabled
     $section_count = 1;
     if ($gBitSystem->isPackageActive('wiki')) {
         require_once WIKI_PKG_PATH . 'BitPage.php';
     }
     // if the object isn't loaded, we'll try and get the content prefs manually
     if (!empty($pCommonObject->mPrefs)) {
         $contentPrefs = $pCommonObject->mPrefs;
     } elseif (empty($pCommonObject->mContentId) && !empty($contentId)) {
         $contentPrefs = $pCommonObject->loadPreferences($contentId);
     }
     // only strip out html if needed
     if ($gBitSystem->isFeatureActive('content_allow_html') || $gBitSystem->isFeatureActive('content_force_allow_html')) {
         // we allow html unconditionally with this parser
     } elseif (!empty($contentPrefs['content_enter_html'])) {
         // we allow html on a per page basis
     } else {
         // we are parsing this page and we either have no way of checking permissions or we have no need for html
         $data = htmlspecialchars($data, ENT_NOQUOTES, 'UTF-8');
     }
     // Extract [link] sections (to be re-inserted later)
     $noparsedlinks = array();
     // This section matches [...].
     // Added handling for [[foo] sections.  -rlpowell
     preg_match_all("/(?<!\\[)\\[([^\\[][^\\]]+)\\]/", $data, $noparseurl);
     foreach (array_unique($noparseurl[1]) as $np) {
         $key = md5(BitSystem::genPass());
         $aux["key"] = $key;
         $aux["data"] = $np;
         $noparsedlinks[] = $aux;
         $data = str_replace("{$np}", $key, $data);
     }
     // Replace special characters
     //done after url catching because otherwise urls of dyn. sites will be modified
     $this->parseHtmlchar($data);
     //$data = strip_tags($data);
     // BiDi markers
     $bidiCount = 0;
     $bidiCount = preg_match_all("/(\\{l2r\\})/", $data, $pages);
     $bidiCount += preg_match_all("/(\\{r2l\\})/", $data, $pages);
     $data = preg_replace("/\\{l2r\\}/", "<div dir='ltr'>", $data);
     $data = preg_replace("/\\{r2l\\}/", "<div dir='rtl'>", $data);
     $data = preg_replace("/\\{lm\\}/", "&lrm;", $data);
     $data = preg_replace("/\\{rm\\}/", "&rlm;", $data);
     // Parse MediaWiki-style pipe syntax tables.
     if ((strpos($data, "{|") === 0 || strpos($data, "\n{|") !== FALSE) && strpos($data, "\n|}") !== FALSE) {
         $data = $this->parseMediawikiTables($data);
     }
     // ============================================= this should go - xing
     // Replace dynamic variables
     // Dynamic variables are similar to dynamic content but they are editable
     // from the page directly, intended for short data, not long text but text
     // will work too
     //     Now won't match HTML-style '%nn' letter codes.
     /*
     		if (preg_match_all("/%([^% 0-9][^% 0-9][^% ]*)%/",$data,$dvars)) {
     			// remove repeated elements
     			$dvars = array_unique($dvars[1]);
     			// Now replace each dynamic variable by a pair composed of the
     			// variable value and a text field to edit the variable. Each
     			foreach($dvars as $dvar) {
     				$query = "select `data` from `".BIT_DB_PREFIX."liberty_dynamic_variables` where `name`=?";
     				$result = $this->mDb->query($query,Array($dvar));
     				if($result->numRows()) {
     					$value = $result->fetchRow();
     					$value = $value["data"];
     				} else {
     					//Default value is NULL
     					$value = "NaV";
     				}
     				// Now build 2 divs
     				$id = 'dyn_'.$dvar;
     
     				if( $gBitUser->hasPermission( 'p_wiki_edit_dynvar' ) ) {
     					$span1 = "<span  style='display:inline;' id='dyn_".$dvar."_display'><a class='dynavar' onclick='javascript:toggle_dynamic_var(\"$dvar\");' title='".tra('Click to edit dynamic variable').": $dvar'>$value</a></span>";
     					$span2 = "<span style='display:none;' id='dyn_".$dvar."_edit'><input type='text' name='dyn_".$dvar."' value='".$value."' /></span>";
     				} else {
     					$span1 = "<span class='dynavar' style='display:inline;' id='dyn_".$dvar."_display'>$value</span>";
     					$span2 = '';
     				}
     				$html = $span1.$span2;
     				//It's important to replace only once
     				$dvar_preg = preg_quote( $dvar );
     				$data = preg_replace("+%$dvar_preg%+",$html,$data,1);
     				//Further replacements only with the value
     				$data = str_replace("%$dvar%",$value,$data);
     
     			}
     			//At the end put an update button
     			//<br /><div style="text-align:center"><input type="submit" name="dyn_update" value="'.tra('Update variables').'"/></div>
     			$data='<form method="post" name="dyn_vars">'.$data.'<div style="display:none;"><input type="submit" name="_dyn_update" value="'.tra('Update variables').'"/></div></form>';
     		}
     */
     // Replace boxes - add a new line that we can have something like: ^!heading^ without the need for a \n after the initial ^ - \n will be removed below
     $data = preg_replace("/\\^([^\\^]+)\\^/", "<div class=\"alert alert-info bitbox\"><!-- bitremovebr -->\n\$1</div>", $data);
     // Replace colors ~~color:text~~
     $data = preg_replace("/\\~\\~([^\\:]+):([^\\~]+)\\~\\~/", "<span style=\"color:\$1;\">\$2</span>", $data);
     // Replace background colors ++color:text++
     $data = preg_replace("/\\+\\+([^\\s][^\\: ]+):([^\\+]+)\\+\\+/", "<span style=\"background:\$1;\">\$2</span>", $data);
     // Underlined text
     $data = preg_replace("/===([^\\=]+)===/", "<span style=\"text-decoration:underline;\">\$1</span>", $data);
     // Center text
     $data = preg_replace("/::(.+?)::/", "<div style=\"text-align:center;\">\$1</div>", $data);
     // Line breaks
     $data = preg_replace('/%%%/', '<br />', $data);
     // reinsert hash-replaced links into page
     foreach ($noparsedlinks as $np) {
         $data = str_replace($np["key"], $np["data"], $data);
     }
     $links = $this->getLinks($data);
     // Note that there're links that are replaced
     foreach ($links as $link) {
         if (strstr($link, $_SERVER["SERVER_NAME"]) || !strstr($link, '//')) {
             $attributes = '';
         } else {
             $attributes = 'class="external"';
         }
         // comments and anonymously created pages get nofollow
         if ($pCommonObject && (get_class($pCommonObject) == 'comments' || isset($pCommonObject->mInfo['user_id']) && $pCommonObject->mInfo['user_id'] == ANONYMOUS_USER_ID)) {
             $attributes .= ' rel="nofollow" ';
         }
         // The (?<!\[) stuff below is to give users an easy way to
         // enter square brackets in their output; things like [[foo]
         // get rendered as [foo]. -rlpowell
         // prepare link for pattern usage
         $link2 = str_replace("/", "\\/", preg_quote($link));
         $pattern = "/(?<!\\[)\\[{$link2}\\|([^\\]\\|]+)([^\\]])*\\]/";
         $data = preg_replace($pattern, "<a {$attributes} href='{$link}'>\$1</a>", $data);
         $pattern = "/(?<!\\[)\\[{$link2}\\]/";
         $data = preg_replace($pattern, "<a {$attributes} href='{$link}'>{$link}</a>", $data);
     }
     // Handle double square brackets.  -rlpowell
     $data = str_replace("[[", "[", $data);
     // now that all links have been taken care of, we can replace all email addresses with the encoded form
     // this will also encode email addressed that have not been linked using []
     $data = encode_email_addresses($data);
     if ($gBitSystem->getConfig('wiki_tables') != 'new') {
         // New syntax for tables
         if (preg_match_all("/\\|\\|(.*)\\|\\|/", $data, $tables)) {
             $maxcols = 1;
             $cols = array();
             for ($i = 0; $i < count($tables[0]); $i++) {
                 $rows = explode('||', $tables[0][$i]);
                 $col[$i] = array();
                 for ($j = 0; $j < count($rows); $j++) {
                     $cols[$i][$j] = explode('|', $rows[$j]);
                     if (count($cols[$i][$j]) > $maxcols) {
                         $maxcols = count($cols[$i][$j]);
                     }
                 }
             }
             for ($i = 0; $i < count($tables[0]); $i++) {
                 $repl = '<table class="table">';
                 for ($j = 0; $j < count($cols[$i]); $j++) {
                     $ncols = count($cols[$i][$j]);
                     if ($ncols == 1 && !$cols[$i][$j][0]) {
                         continue;
                     }
                     $repl .= '<tr class="' . ($j % 2 ? 'even' : 'odd') . '">';
                     for ($k = 0; $k < $ncols; $k++) {
                         $repl .= '<td ';
                         if ($k == $ncols - 1 && $ncols < $maxcols) {
                             $repl .= ' colspan="' . ($maxcols - $k) . '"';
                         }
                         $repl .= '>' . $cols[$i][$j][$k] . '</td>';
                     }
                     $repl .= '</tr>';
                 }
                 $repl .= '</table>';
                 $data = str_replace($tables[0][$i], $repl, $data);
             }
         }
     } else {
         // New syntax for tables
         // REWRITE THIS CODE
         if (preg_match_all("/\\|\\|(.*?)\\|\\|/s", $data, $tables)) {
             $maxcols = 1;
             $cols = array();
             for ($i = 0; $i < count($tables[0]); $i++) {
                 $rows = preg_split("/(\n|\\<br\\/\\>)/", $tables[0][$i]);
                 $col[$i] = array();
                 for ($j = 0; $j < count($rows); $j++) {
                     $rows[$j] = str_replace('||', '', $rows[$j]);
                     $cols[$i][$j] = explode('|', $rows[$j]);
                     if (count($cols[$i][$j]) > $maxcols) {
                         $maxcols = count($cols[$i][$j]);
                     }
                 }
             }
             for ($i = 0; $i < count($tables[0]); $i++) {
                 $repl = '<table class="table table-striped">';
                 if (preg_match("#^~#", $cols[$i][0][0]) && ($cols[$i][0][0] = preg_replace("#^~#", "", $cols[$i][0][0]))) {
                     $th = TRUE;
                 } else {
                     $th = FALSE;
                 }
                 for ($j = 0; $j < count($cols[$i]); $j++) {
                     $ncols = count($cols[$i][$j]);
                     if ($ncols == 1 && !$cols[$i][$j][0]) {
                         continue;
                     }
                     if ($j == 0 && $th) {
                         $repl .= '<tr>';
                     } else {
                         $repl .= '<tr class="' . ($j % 2 ? 'odd' : 'even') . '">';
                     }
                     for ($k = 0; $k < $ncols; $k++) {
                         $thd = $j == 0 && $th ? 'th' : 'td';
                         $repl .= "<{$thd}";
                         if ($k == $ncols - 1 && $ncols < $maxcols) {
                             $repl .= ' colspan="' . ($maxcols - $k) . '"';
                         }
                         $repl .= ">" . str_replace("\\n", "<br />", $cols[$i][$j][$k]) . "</{$thd}>";
                     }
                     $repl .= '</tr>';
                 }
                 $repl .= '</table>';
                 $data = str_replace($tables[0][$i], $repl, $data);
             }
         }
     }
     // Now tokenize the expression and process the tokens
     // Use tab and newline as tokenizing characters as well  ////
     $lines = explode("\n", $data);
     $data = '';
     $listbeg = array();
     $divdepth = array();
     $inTable = 0;
     // loop: process all lines
     foreach ($lines as $line) {
         // bitweaver now ignores leading space because it is *VERY* disturbing to unaware users - spiderr
         // unless 'feature_wiki_preserve_leading_blanks is set'.  This is used for sites that have
         // migrated from TikiWiki and have lots of pages whose formatting depends on the presevation of leading spaces
         if (!$gBitSystem->isFeatureActive('wiki_preserve_leading_blanks')) {
             $line = trim($line);
         }
         // check if we are inside a table, if so, ignore monospaced and do
         // not insert <br/>
         $inTable += substr_count($line, "<table");
         $inTable -= substr_count($line, "</table");
         // If the first character is ' ' and we are not in pre then we are in pre
         // bitweaver now ignores leading space because it is *VERY* disturbing to unaware users - spiderr
         if (substr($line, 0, 1) == ' ' && $gBitSystem->isFeatureActive('wiki_monosp') && $inTable == 0) {
             // This is not list item -- must close lists currently opened
             while (count($listbeg)) {
                 $data .= array_shift($listbeg);
             }
             // If the first character is space then
             // change spaces for &nbsp;
             $line = '<span style="font-family:monospace;">' . str_replace(' ', '&nbsp;', substr($line, 1)) . '</span>';
         }
         // Title bars
         $line = preg_replace("/\\-\\=([^=]+)\\=\\-/", "<div class='bitbar'>\$1</div><!-- bitremovebr -->", $line);
         // Monospaced text
         $line = preg_replace("/-\\+(.*?)\\+-/", "<code>\$1</code>", $line);
         // Bold text
         $line = preg_replace("/__(.*?)__/", "<strong>\$1</strong>", $line);
         // Italics
         $line = preg_replace("/''(.*?)''/", "<em>\$1</em>", $line);
         // Definition lists
         $line = preg_replace("/^;([^:]+):(.+)/", "<dl><dt>\$1</dt><dd>\$2</dd></dl><!-- bitremovebr -->", $line);
         // This line is parseable then we have to see what we have
         if (substr($line, 0, 3) == '---') {
             // This is not list item -- must close lists currently opened
             while (count($listbeg)) {
                 $data .= array_shift($listbeg);
             }
             $line = '<hr/>';
         } else {
             $litype = substr($line, 0, 1);
             if ($litype == '*' || $litype == '#') {
                 $listlevel = $this->howManyAtStart($line, $litype);
                 $liclose = '</li>';
                 $addremove = 0;
                 if ($listlevel < count($listbeg)) {
                     while ($listlevel != count($listbeg)) {
                         $data .= array_shift($listbeg);
                     }
                     if (substr(current($listbeg), 0, 5) != '</li>') {
                         $liclose = '';
                     }
                 } elseif ($listlevel > count($listbeg)) {
                     $listyle = '';
                     while ($listlevel != count($listbeg)) {
                         array_unshift($listbeg, $litype == '*' ? '</ul>' : '</ol>');
                         if ($listlevel == count($listbeg)) {
                             $listate = substr($line, $listlevel, 1);
                             if (($listate == '+' || $listate == '-') && !($litype == '*' && !strstr(current($listbeg), '</ul>') || $litype == '#' && !strstr(current($listbeg), '</ol>'))) {
                                 $thisid = 'id' . microtime() * 1000000;
                                 $data .= '<br /><a id="flipper' . $thisid . '" href="javascript:flipWithSign(\'' . $thisid . '\',1)">[' . ($listate == '-' ? '+' : '-') . ']</a>';
                                 $listyle = ' id="' . $thisid . '" style="display:' . ($listate == '+' ? 'block' : 'none') . ';"';
                                 $addremove = 1;
                             }
                         }
                         $data .= $litype == '*' ? "<ul{$listyle}>" : "<ol{$listyle}>";
                     }
                     $liclose = '';
                 }
                 if ($litype == '*' && !strstr(current($listbeg), '</ul>') || $litype == '#' && !strstr(current($listbeg), '</ol>')) {
                     $data .= array_shift($listbeg);
                     $listyle = '';
                     $listate = substr($line, $listlevel, 1);
                     if ($listate == '+' || $listate == '-') {
                         $thisid = 'id' . microtime() * 1000000;
                         $data .= '<br /><a id="flipper' . $thisid . '" href="javascript:flipWithSign(\'' . $thisid . '\',1)">[' . ($listate == '-' ? '+' : '-') . ']</a>';
                         $listyle = ' id="' . $thisid . '" style="display:' . ($listate == '+' ? 'block' : 'none') . ';"';
                         $addremove = 1;
                     }
                     $data .= $litype == '*' ? "<ul{$listyle}>" : "<ol{$listyle}>";
                     $liclose = '';
                     array_unshift($listbeg, $litype == '*' ? '</li></ul>' : '</li></ol>');
                 }
                 $line = $liclose . '<li>' . substr($line, $listlevel + $addremove);
                 if (substr(current($listbeg), 0, 5) != '</li>') {
                     array_unshift($listbeg, '</li>' . array_shift($listbeg));
                 }
             } elseif ($litype == '+') {
                 // Must append paragraph for list item of given depth...
                 $listlevel = $this->howManyAtStart($line, $litype);
                 // Close lists down to requested level
                 while ($listlevel < count($listbeg)) {
                     $data .= array_shift($listbeg);
                 }
                 if (count($listbeg)) {
                     if (substr(current($listbeg), 0, 5) != '</li>') {
                         array_unshift($listbeg, '</li>' . array_shift($listbeg));
                         $liclose = '<li>';
                     } else {
                         $liclose = '<br />';
                     }
                 } else {
                     $liclose = '';
                 }
                 $line = $liclose . substr($line, count($listbeg));
             } else {
                 // This is not list item -- must close lists currently opened
                 while (count($listbeg)) {
                     $data .= array_shift($listbeg);
                 }
                 // Get count of (possible) header signs at start
                 $hdrlevel = $this->howManyAtStart($line, '!');
                 // If 1st char on line is '!' and its count less than 6 (max in HTML)
                 if ($litype == '!' && $hdrlevel > 0 && $hdrlevel <= 6) {
                     // OK. Parse headers here...
                     $aclose = '';
                     $edit_link = '';
                     $addremove = 0;
                     // Close lower level divs if opened
                     for (; current($divdepth) >= $hdrlevel; array_shift($divdepth)) {
                         $data .= '</div>';
                     }
                     // May be spesial signs present after '!'s?
                     $divstate = substr($line, $hdrlevel, 1);
                     if ($divstate == '+' || $divstate == '-') {
                         // OK. Must insert flipper after HEADER, and then open new div...
                         $thisid = 'id' . microtime() * 1000000;
                         $aclose = '<a id="flipper' . $thisid . '" href="javascript:flipWithSign(\'' . $thisid . '\',1)">[' . ($divstate == '-' ? '+' : '-') . ']</a>';
                         $aclose .= '<div id="' . $thisid . '" style="display:' . ($divstate == '+' ? 'block' : 'none') . ';">';
                         array_unshift($divdepth, $hdrlevel);
                         $addremove = 1;
                     }
                     if ($gBitSystem->isFeatureActive('wiki_section_edit') && $gBitUser->hasPermission('p_wiki_update_page')) {
                         if ($hdrlevel == $gBitSystem->getConfig('wiki_section_edit')) {
                             $edit_url = WIKI_PKG_URL . "edit.php?content_id=" . $contentId . "&amp;section=" . $section_count++;
                             $edit_link = '<span class="editsection" style="float:right;margin-left:5px;">[<a href="' . $edit_url . '">' . tra("edit") . '</a>]</span>';
                         }
                     }
                     $hTagLevel = $hdrlevel + 1;
                     // there should only be 1 <h1> per html document
                     $line = $edit_link . "<h{$hTagLevel}>" . substr($line, $hdrlevel + $addremove) . "</h{$hTagLevel}>" . $aclose;
                 } elseif (!strcmp($line, "...page...")) {
                     // Close lists and divs currently opened
                     while (count($listbeg)) {
                         $data .= array_shift($listbeg);
                     }
                     while (count($divdepth)) {
                         $data .= '</div>';
                         array_shift($divdepth);
                     }
                     // Leave line unchanged... index.php will split wiki here
                     $line = "...page...";
                 } else {
                     // Usual paragraph.
                     if ($inTable == 0) {
                         $line .= '<br />';
                     }
                 }
             }
         }
         $data .= $line;
     }
     // Close lists may remains opened
     while (count($listbeg)) {
         $data .= array_shift($listbeg);
     }
     // Close header divs may remains opened
     for ($i = 1; $i <= count($divdepth); $i++) {
         $data .= '</div>';
     }
     // Close BiDi DIVs if any
     for ($i = 0; $i < $bidiCount; $i++) {
         $data .= "</div>";
     }
     $data = str_replace("<!-- bitremovebr --><br />", "", $data);
     return $data;
 }