. // Copyright © 2007-2014 Erwan Briand // // This program is free software: you can redistribute it and/or modify it // under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, version 3 only. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public // License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . /** * @file * This file contains the Textview class * * Get a textarea (with optional Javascript content). * Parse texts for CodingTeam. */ /* The following two lines are ugly, yes. * But, it's the more "sexy" way to do what I want to do: * allow users to click a line number for each code posted * on a page and avoid conflicts. */ global $textview_number_of_code_in_this_page; $textview_number_of_code_in_this_page = 0; /** * Textview class */ class Textview { private $value, $id; /** * Load the view * * Generate a pretty textarea with optional Javascript content. * @param $value * The content of the textarea. * @param $check * If TRUE, allow_nl2br is checked. * @param $serious (optional) * If TRUE, don't show the toolbar. * @param $tiny (optional) * If TRUE, show a tiny textarea. * @return * The pretty textarea. */ function loadView ($value, $check=TRUE, $serious=FALSE, $tiny=FALSE) { $this->value = $value; $this->id = 'text'; // Include programming languages list require(CT_BASEDIR.'/inc/data/language.php'); // Require functions.js // If Javascript is disabled, this functions are not shown to the user $view = "
".i18n('Authorized (X)HTML tags: %(markups)s.', array('markups' => 'a, img, abbr, blockquote, code, ul, ol, li, h3, h4, p, br, hr, strong, em, pre, sub, sup, table, caption, thead, tr, th, tfoot, tbody, td')).""; return $view; } /** * Prepare * * Parse users's HTML * @param $txt * The text that have to be prepared. * @param $allow_nl2br (optional) * The nl2br rule. * @param $is_wiki (optional) * TRUE if the text is from a wiki. * @return * The safe text. */ function prepare($txt, $nl2br=TRUE, $is_wiki=FALSE) { global $allow_nl2br; $allow_nl2br = (bool)$nl2br; if (!function_exists('code_parse')) { /** * Code parse * * Use GESHI to colorize the code * @param $code * The code. * @return * The colorized code. */ function code_parse($code) { if (!empty($code[2])) { $lang = $code[1]; $txt = $code[2]; require(CT_BASEDIR.'/inc/data/language.php'); if(array_key_exists($lang, $language) && file_exists(CT_BASEDIR.'/inc/libs/geshi/'.$lang.'.php')) $lang = $lang; else $lang = 'text'; } else { $txt = $code[1]; $lang = 'text'; } global $textview_number_of_code_in_this_page; $textview_number_of_code_in_this_page ++; $hash = $textview_number_of_code_in_this_page; global $allow_nl2br; if ($allow_nl2br) { $cleantxt = ''; foreach (explode("\n", $txt) as $line) { $line = str_replace("\r", '', $line); if (mb_substr($line, -6, mb_strlen($line)) == '
') $cleantxt .= mb_substr($line, 0, -6)."\n"; else $cleantxt .= $line."\n"; } $cleantxt = mb_substr($cleantxt, 0, -1); } else $cleantxt = $txt; $link = array($_SERVER['REQUEST_URI'], 'c'.$hash); $code = HTMLSourceView($cleantxt, $lang, FALSE, $link, TRUE); return $code; } } // Add automatic line breaks and correct uggly known errors if ($allow_nl2br) { $txt = nl2br($txt); $arr0 = array('

    ', '
    ', '

', '
', '
', '

', '
', '
','
', '
', '
', '
', '
', '
', '
', '
'); $arr1 = array('
    ', '', '
', '', '', '
', '', '', '', '', '', '', '', '', '', ''); $txt = str_replace($arr0, $arr1, $txt); } // Match all `code` markups $txt = preg_replace_callback('#\(.+?)\#si','code_parse', $txt); $txt = preg_replace_callback('#\(.+?)\#si','code_parse', $txt); // Removing markups if not in list. $allowed_tags = array('a', 'img', 'abbr', 'blockquote', 'code', 'ul', 'ol', 'li', 'h3', 'h4', 'p', 'br', 'hr', 'strong', 'em', 'pre', 'sub', 'sup', 'table', 'caption', 'thead', 'tr', 'th', 'tfoot', 'tbody', 'td', 'div', 'span' /* two tags needed for code colorization */); // Edit all markups that are not in the allowed list preg_match_all('!<\s*(/)?\s*([a-zA-Z0-9]+)[^>]*>!', $txt, $all_tags); array_shift($all_tags); $slashes = $all_tags[0]; $all_tags = $all_tags[1]; foreach ($all_tags as $i => $tag) if (!in_array($tag, $allowed_tags)) $txt = preg_replace('!<(\s*'.$slashes[$i].'\s*'.$tag.'[^>]*)>!', '<'.'$1'.'>', $txt); // Delete all attributes listed below $all_attributes = "'\\s(onerror|onload|onunload|onchange|onsubmit|onreset|onselect|onblur|onfocus|onkeydown|onkeypress|onkeyup|onclick|ondblclick|onmousedown|onmousemove|onmouseover|onmouseout|onmouseup)=(\"|\')(.*?)(\"|\')'i"; $txt = preg_replace($all_attributes, '', $txt); //Special rules if the text is a page from a wiki if ($is_wiki) { // Set the name of the project global $projectdbname; $projectdbname = $is_wiki; /** * Wiki parse * * Treatment for forced wiki link via [wiki=PageName Link name] * @param $arg * The text matched by preg_replace_callback. * @return * The link. */ function wiki_parse($arg) { global $projectdbname; if ($arg[0][0] == '!') return mb_substr($arg[0], 1); else if (mb_ereg("^(([A-Z]{1}[a-z]+){2,})$", $arg[1])) return $arg[0][0].''.$arg[3].''; else return $arg[0]; } $txt = preg_replace_callback('#[^.]\[wiki=(([A-Z]{1}[a-z]+){2,})\s(.+?)\]#s', 'wiki_parse', $txt); /** * Wiki parse automatic * * Treatment for automatic wiki link via Pagename * @param $arg * The text matched by preg_replace_callback. * @return * The link. */ function wiki_parse_automatic($arg) { global $projectdbname; if ($arg[0][0] == '!') return mb_substr($arg[0], 1); elseif ($arg[0][0] == '/') return $arg[0][0].$arg[1]; else return $arg[0][0].''.$arg[1].''; } $txt = preg_replace_callback('#[^.](([A-Z]{1}[a-z]+){2,})#s', 'wiki_parse_automatic', $txt); // Generate the menu with

/

global $menu, $i; $menu = array(); $i = 0; /** * Generate the menu * * Use all the h3 and h4 of the text to generate a menu * @param $arg * The text matched by preg_replace_callback. * @return * The menu. */ function gen_menu($arg) { global $menu, $i; if (mb_substr($arg[0], 0, 4) == '

' && array_key_exists(count($menu) - 1, $menu)) $id = array_push($menu[count($menu) - 1][1], $arg[1]); else $id = array_push($menu, array($arg[1] , array())); if (mb_substr($arg[0], 0, 4) == '

') $return = '

'.$arg[1].'

'; else { $return = '

'.$arg[1].'

'; $i ++; } return $return; } $txt = preg_replace_callback('#(.+?)#s', 'gen_menu', $txt); return array('menu' => $menu, 'content' => $txt); } else return $txt; } } ?>