* * Licensed under AGPLv3 * (see COPYING for full license text) * */ namespace service; class renderer { /** * @param $output_cache output cache object * @param $mfile mfile object * @param $data data for the rendering of views */ public function __construct($output_cache, $mfile, $data) { $this->output_cache = $output_cache; $this->mfile = $mfile; $this->data = $data; } private function colorify($file, $lexer, $anchor_id = false) { $output = ""; $lines_to_remove = 0; $output .= '
'."\n"; $output .= '
'."\n"; $content = file_get_contents($file); $linecount = count(explode("\n", $content)); $content = $this->reformat_json($lexer, $linecount, $content); if ($lexer == "ascii") { // TODO: use exec safe and catch exception $ret = (new \libraries\ProcRunner(array('ansi2html', '-p'))) ->input($content) ->forbid_stderr() ->exec(); // Last line is empty $lines_to_remove = 1; } else { // TODO: use exec safe and catch exception $ret = (new \libraries\ProcRunner(array('pygmentize', '-F', 'codetagify', '-O', 'encoding=guess,outencoding=utf8,stripnl=False', '-l', $lexer, '-f', 'html'))) ->input($content) ->exec(); // Last 2 items are "
" and "" $lines_to_remove = 2; } $buf = explode("\n", $ret["stdout"]); $line_count = count($buf); for ($i = 1; $i <= $lines_to_remove; $i++) { unset($buf[$line_count - $i]); } foreach ($buf as $key => $line) { $line_number = $key + 1; if ($key == 0) { $line = str_replace("
", "", $line);
			}

			$anchor = "n$line_number";
			if ($anchor_id !== false) {
				$anchor = "n-$anchor_id-$line_number";
			}

			if ($line === "") {
				$line = "
"; } // Be careful not to add superflous whitespace here (we are in a ) $output .= "
" ."" ." " ."" ."".$line."
"; } $output .= "
"; $output .= "
"; return array( "return_value" => $ret["return_code"], "output" => $output ); } public function highlight_file($filedata, $lexer, $is_multipaste) { // highlight the file and cache the result, fall back to plain text if $lexer fails foreach (array($lexer, "text") as $lexer) { $highlit = cache_function($filedata['data_id'].'_'.$lexer, 100, function() use ($filedata, $lexer, $is_multipaste) { $file = $this->mfile->file($filedata['data_id']); if ($lexer == "rmd") { ob_start(); echo '
'."\n"; echo '
'."\n"; echo '
'."\n"; require_once(APPPATH."/third_party/parsedown/Parsedown.php"); $parsedown = new \Parsedown(); echo $parsedown->text(file_get_contents($file)); echo '
'; return array( "output" => ob_get_clean(), "return_value" => 0, ); } else { return $this->colorify($file, $lexer, $is_multipaste ? $filedata["id"] : false); } }); if ($highlit["return_value"] == 0) { break; } else { $message = "Error trying to process the file. Either the lexer is unknown or something is broken."; if ($lexer != "text") { $message .= " Falling back to plain text."; } $this->output_cache->render_now( array("error_message" => "

$message

"), "file/fragments/alert-wide" ); } } $data = array_merge($this->data, array( 'title' => htmlspecialchars($filedata['filename']), 'id' => $filedata["id"], 'current_highlight' => htmlspecialchars($lexer), 'timeout' => $this->mfile->get_timeout_string($filedata["id"]), 'filedata' => $filedata, )); $this->output_cache->render_now($data, 'file/html_paste_header'); $this->output_cache->render_now($highlit["output"]); $this->output_cache->render_now($data, 'file/html_paste_footer'); } /** * @param $lexer * @param $linecount * @param $content * @return string */ private function reformat_json($lexer, $linecount, $content) { if ($lexer === "json" && $linecount === 1) { $decoded_json = json_decode($content); if ($decoded_json !== null && $decoded_json !== false) { $pretty_json = json_encode($decoded_json, JSON_PRETTY_PRINT); if ($pretty_json !== false) { $content = $pretty_json; $this->output_cache->render_now( array( "error_type" => "alert-info", "error_message" => "

The file below has been reformated for readability. It may differ from the original.

" ), "file/fragments/alert-wide" ); } } } return $content; } }