"cpp", "h" => "cpp", "hpp" => "cpp", "rc"=>"text", "sh"=>"bash", "cs"=>"csharp"); public static $syntaxhighlightext = array("html", "as3", "cf", "cpp", "c", "css", "pas", "diff", "patch", "erl", "java", "jfx", "js", "pl", "php", "py", "rb", "sass", "scss", "scala", "sql", "vb", ); /** * Test if an extension is supported by the syntax highlighter. * * @param string The extension to test * @return bool */ public static function isSupportedExtension($extension) { return in_array($extension, self::$supportedExtenstions); } /** * Returns a HTML snippet with a line-by-line pre-rendered table * for the given source content * * @param array file information as returned by getMimeType or getMimeTypeFromContent * @param string the content of the file * @return string */ public static function highLight($fileinfo, $content, $url) { if (self::isText($fileinfo)) { $pretty = ''; if (self::isSupportedExtension($fileinfo[2])) { $pretty = ' prettyprint'; } $table = array(); $i = 1; /*foreach (self::splitIntoLines($content) as $line) { $table[] = ''.$i.'' .''.self::emphasizeControlCharacters(Pluf_esc($line)).''; $i++; } return Pluf_Template::markSafe(implode("\n", $table));*/ //var_dump($fileinfo); $ext = ""; if (in_array($fileinfo[2], self::$syntaxhighlightext)) $ext = $fileinfo[2]; elseif (array_key_exists($fileinfo[2], self::$map)) $ext = self::$map[$fileinfo[2]]; else $ext = "text"; if ($ext == "php" || $ext == "html" || $ext == "htm" || $ext == "js") $content = '
' . str_replace("<", "<", $content) . '
'; else $content = '
'; } if (self::isImage($fileinfo)) { $content = ''; $content .= '' . $fileinfo[1] . ''; } return Pluf_Template::markSafe($content); } /** * Find the mime type of a file. * * Use /etc/mime.types to find the type. * * @param string Filename/Filepath * @param array Mime type found or 'application/octet-stream', basename, extension */ public static function getMimeType($file) { static $mimes = null; if ($mimes == null) { $mimes = array(); $src = Pluf::f('idf_mimetypes_db', '/etc/mime.types'); $filecontent = @file_get_contents($src); if ($filecontent !== false) { $mimes = preg_split("/\015\012|\015|\012/", $filecontent); } } $info = pathinfo($file); if (isset($info['extension'])) { $extension = strtolower($info["extension"]); foreach ($mimes as $mime) { if ('#' != substr($mime, 0, 1)) { $elts = preg_split('/ |\t/', $mime, -1, PREG_SPLIT_NO_EMPTY); if (in_array($extension, $elts)) { return array($elts[0], $info['basename'], $info['extension']); } } } } else { // we consider that if no extension and base name is all // uppercase, then we have a text file. if ($info['basename'] == strtoupper($info['basename'])) { return array('text/plain', $info['basename'], 'txt'); } $info['extension'] = 'bin'; } return array('application/octet-stream', $info['basename'], $info['extension']); } /** * Find the mime type of a file using the fileinfo class. * * @param string Filename/Filepath * @param string File content * @return array Mime type found or 'application/octet-stream', basename, extension */ public static function getMimeTypeFromContent($file, $filedata) { // There is a bug/memory leak in finfo_buffer // finfo_buffer works 99% of the time - so rather than // replacing it with some complex mime check system - just create // a list of extensions that we know // And document the types best we can: // po is a translation file in indefero - tried text/plain but the syntax highlight JS library didn't like it $ext_hack = array("po" => "text/plain"); $info = pathinfo($file); $res = array('application/octet-stream', $info['basename'], isset($info['extension']) ? $info['extension'] : 'bin'); if ($info && isset($info["extension"]) && array_key_exists($info["extension"], $ext_hack)) { $res[0] = $ext_hack[$info["extension"]]; return $res; } if (function_exists('finfo_open')) { $finfo = finfo_open(FILEINFO_MIME); $mime = finfo_buffer($finfo, $filedata); finfo_close($finfo); if ($mime) { $res[0] = $mime; } if (!isset($info['extension']) && $mime) { $res[2] = (0 === strpos($mime, 'text/')) ? 'txt' : 'bin'; } elseif (!isset($info['extension'])) { $res[2] = 'bin'; } } return $res; } /** * Splits a string into separate lines while retaining the individual * line ending character for every line. * * OS 9 line endings are not supported. * * @param string content * @param boolean if true, skip completely empty lines * @return string */ public static function splitIntoLines($content, $skipEmpty = false) { $last_off = 0; $lines = array(); while (preg_match("/\r\n|\n/", $content, $m, PREG_OFFSET_CAPTURE, $last_off)) { $next_off = strlen($m[0][0]) + $m[0][1]; $line = substr($content, $last_off, $next_off - $last_off); $last_off = $next_off; if ($line !== $m[0][0] || !$skipEmpty) $lines[] = $line; } $line = substr($content, $last_off); if ($line !== false && strlen($line) > 0) $lines[] = $line; return $lines; } /** * This translates most of the C0 ASCII control characters into * their visual counterparts in the 0x24## unicode plane * (http://en.wikipedia.org/wiki/C0_and_C1_control_codes). * * We could add DEL (0x7F) to this set, but unfortunately this * is not nicely mapped to 0x247F in the control plane, but 0x2421 * and adding an if expression below just for this is a little bit * of a hassle. And of course, the more esoteric ones from C1 are * missing as well... * * @param string $content * @return string */ public static function emphasizeControlCharacters($content) { return preg_replace( '/([\x00-\x1F])/ue', '"$".bin2hex("\\1").""', $content); } /** * Find if a given mime type is a text file. * This uses the output of the self::getMimeType function. * * @param array (Mime type, file name, extension) * @return bool Is text */ public static function isText($fileinfo) { if (0 === strpos($fileinfo[0], 'text/')) { return true; } $ext = 'mdtext php-dist h gitignore diff patch'; $extra_ext = trim(Pluf::f('idf_extra_text_ext', '')); if (!empty($extra_ext)) $ext .= ' ' . $extra_ext; $ext = array_merge(self::$supportedExtenstions, explode(' ' , $ext)); return (in_array($fileinfo[2], $ext)); } public static function isImage($fileinfo) { if (0 === strpos($fileinfo[0], 'image/')) { return true; } return false; } }